Commit 3c214245 authored by Russell Dickenson's avatar Russell Dickenson

Merge branch 'alexives/update_docs_on_single_table_inheritance' into 'master'

Docs single table inheritance in migrations

See merge request gitlab-org/gitlab!63327
parents de873efa b1fe8180
......@@ -255,12 +255,8 @@ batches instead of doing this one by one:
class ScheduleExtractServicesUrl < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
class Service < ActiveRecord::Base
self.table_name = 'services'
end
def up
Service.select(:id).in_batches do |relation|
define_batchable_model('services').select(:id).in_batches do |relation|
jobs = relation.pluck(:id).map do |id|
['ExtractServicesUrl', [id]]
end
......@@ -286,18 +282,12 @@ this:
class ConsumeRemainingExtractServicesUrlJobs < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
class Service < ActiveRecord::Base
include ::EachBatch
self.table_name = 'services'
end
def up
# This must be included
Gitlab::BackgroundMigration.steal('ExtractServicesUrl')
# This should be included, but can be skipped - see below
Service.where(url: nil).each_batch(of: 50) do |batch|
define_batchable_model('services').where(url: nil).each_batch(of: 50) do |batch|
range = batch.pluck('MIN(id)', 'MAX(id)').first
Gitlab::BackgroundMigration::ExtractServicesUrl.new.perform(*range)
......
......@@ -976,6 +976,9 @@ If using a model in the migrations, you should first
[clear the column cache](https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema/ClassMethods.html#method-i-reset_column_information)
using `reset_column_information`.
If using a model that leverages single table inheritance (STI), there are [special
considerations](single_table_inheritance.md#in-migrations).
This avoids problems where a column that you are using was altered and cached
in a previous migration.
......
......@@ -22,3 +22,42 @@ The solution is very simple: just use a separate table for every type you'd
otherwise store in the same table. For example, instead of having a `keys` table
with `type` set to either `Key` or `DeployKey` you'd have two separate tables:
`keys` and `deploy_keys`.
## In migrations
Whenever a model is used in a migration, single table inheritance should be disabled.
Due to the way Rails loads associations (even in migrations), failing to disable STI
could result in loading unexpected code or associations which may cause unintended
side effects or failures during upgrades.
```ruby
class SomeMigration < ActiveRecord::Migration[6.0]
class Services < ActiveRecord::Base
self.table_name = 'services'
self.inheritance_column = :_type_disabled
end
def up
...
```
If nothing needs to be added to the model other than disabling STI or `EachBatch`,
use the helper `define_batchable_model` instead of defining the class.
This ensures that the migration loads the columns for the migration in isolation,
and the helper disables STI by default.
```ruby
class EnqueueSomeBackgroundMigration < ActiveRecord::Migration[6.0]
disable_ddl_transaction!
def up
define_batchable_model('services').select(:id).in_batches do |relation|
jobs = relation.pluck(:id).map do |id|
['ExtractServicesUrl', [id]]
end
BackgroundMigrationWorker.bulk_perform_async(jobs)
end
end
...
```
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment