From a09983ae35713f5a2bbb100981116d31ce99826e Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 20 Jul 2020 12:26:25 +0000 Subject: Add latest changes from gitlab-org/gitlab@13-2-stable-ee --- doc/development/migration_style_guide.md | 44 ++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'doc/development/migration_style_guide.md') diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 7d3d9dac174..d1f956f957e 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -88,7 +88,7 @@ body: For example: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] DOWNTIME = true DOWNTIME_REASON = 'This migration requires downtime because ...' @@ -411,7 +411,7 @@ migration. For this to work your migration needs to include the module `Gitlab::Database::MultiThreadedMigration`: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers include Gitlab::Database::MultiThreadedMigration end @@ -421,7 +421,7 @@ You can then use the method `with_multiple_threads` to perform work in separate threads. For example: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers include Gitlab::Database::MultiThreadedMigration @@ -455,7 +455,7 @@ by calling the method `disable_ddl_transaction!` in the body of your migration class like so: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers disable_ddl_transaction! @@ -495,9 +495,11 @@ by calling the method `disable_ddl_transaction!` in the body of your migration class like so: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers + DOWNTIME = false + disable_ddl_transaction! def up @@ -534,7 +536,7 @@ Here's an example where we add a new column with a foreign key constraint. Note it includes `index: true` to create an index for it. ```ruby -class Migration < ActiveRecord::Migration[4.2] +class Migration < ActiveRecord::Migration[6.0] def change add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } @@ -602,7 +604,8 @@ In this particular case, the default value exists and we're just changing the me `request_access_enabled` column, which does not imply a rewrite of all the existing records in the `namespaces` table. Only when creating a new column with a default, all the records are going be rewritten. -NOTE: **Note:** A faster [ALTER TABLE ADD COLUMN with a non-null default](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) +NOTE: **Note:** +A faster [ALTER TABLE ADD COLUMN with a non-null default](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) was introduced on PostgresSQL 11.0, removing the need of rewriting the table when a new column with a default value is added. For the reasons mentioned above, it's safe to use `change_column_default` in a single-transaction migration @@ -808,6 +811,14 @@ class BuildMetadata end ``` +When using a `JSONB` column, use the [JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb) to keep control of the data being inserted over time. + +```ruby +class BuildMetadata + validates :config_options, json_schema: { filename: 'build_metadata_config_option' } +end +``` + ## Testing See the [Testing Rails migrations](testing_guide/testing_migrations_guide.md) style guide. @@ -844,16 +855,33 @@ If you need more complex logic, you can define and use models local to a migration. For example: ```ruby -class MyMigration < ActiveRecord::Migration[4.2] +class MyMigration < ActiveRecord::Migration[6.0] class Project < ActiveRecord::Base self.table_name = 'projects' end + + def up + # Reset the column information of all the models that update the database + # to ensure the Active Record's knowledge of the table structure is current + Project.reset_column_information + + # ... ... + end end ``` When doing so be sure to explicitly set the model's table name, so it's not derived from the class name or namespace. +Finally, make sure that `reset_column_information` is run in the `up` method of +the migration for all local Models that update the database. + +The reason for that is that all migration classes are loaded at the beginning +(when `db:migrate` starts), so they can get out of sync with the table schema +they map to in case another migration updates that schema. That makes the data +migration fail when trying to insert or make updates to the underlying table, +as the new columns are reported as `unknown attribute` by `ActiveRecord`. + ### Renaming reserved paths When a new route for projects is introduced, it could conflict with any -- cgit v1.2.3