diff --git a/lib/safe-pg-migrations/helpers/batch_over.rb b/lib/safe-pg-migrations/helpers/batch_over.rb index d256b8ec..37668145 100644 --- a/lib/safe-pg-migrations/helpers/batch_over.rb +++ b/lib/safe-pg-migrations/helpers/batch_over.rb @@ -2,6 +2,25 @@ module SafePgMigrations module Helpers + # This helper class allows to iterate over records in batches, in a similar + # way to ActiveRecord's `in_batches` method with the :use_ranges option, + # which was introduced in ActiveRecord 7.1. + # + # See: + # - https://api.rubyonrails.org/classes/ActiveRecord/Batches.html#method-i-in_batches + # - https://github.com/rails/rails/blob/v7.1.0/activerecord/CHANGELOG.md + # - https://github.com/rails/rails/pull/45414 + # - https://github.com/rails/rails/commit/620f24782977b8e53e06cf0e2c905a591936e990 + # + # If using ActiveRecord 7.1 or later, it's recommended to use the built-in + # method, e.g. + # + # User.in_batches(of: 100, use_ranges: true).each { |batch| ... } + # + # Otherwise, this helper can be used as a fallback: + # + # SafePgMigrations::Helpers::BatchOver.new(User, of: 100).each_batch { |batch| ... } + # class BatchOver def initialize(model, of: SafePgMigrations.config.backfill_batch_size) @model = model diff --git a/lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb b/lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb index cd573162..3866ebb0 100644 --- a/lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb +++ b/lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb @@ -53,11 +53,19 @@ def backfill_column_default(table_name, column_name) Helpers::Logger.say_method_call(:backfill_column_default, table_name, column_name) - Helpers::BatchOver.new(model).each_batch do |batch| + batch_handler = lambda do |batch| batch.update_all("#{quoted_column_name} = DEFAULT") sleep SafePgMigrations.config.backfill_pause end + + backfill_batch_size = SafePgMigrations.config.backfill_batch_size + + if ActiveRecord.version >= Gem::Version.new('7.1') + model.in_batches(of: backfill_batch_size, use_ranges: true).each(&batch_handler) + else + Helpers::BatchOver.new(model, of: backfill_batch_size).each_batch(&batch_handler) + end end end end