Class: OnlineMigrations::BackgroundDataMigrations::CopyColumn
- Inherits:
-
DataMigration
- Object
- DataMigration
- OnlineMigrations::BackgroundDataMigrations::CopyColumn
- Defined in:
- lib/online_migrations/background_data_migrations/copy_column.rb
Instance Attribute Summary collapse
-
#copy_from ⇒ Object
readonly
Returns the value of attribute copy_from.
-
#copy_to ⇒ Object
readonly
Returns the value of attribute copy_to.
-
#model_name ⇒ Object
readonly
Returns the value of attribute model_name.
-
#table_name ⇒ Object
readonly
Returns the value of attribute table_name.
-
#type_cast_functions ⇒ Object
readonly
Returns the value of attribute type_cast_functions.
Instance Method Summary collapse
- #collection ⇒ Object
- #count ⇒ Object
-
#initialize(table_name, copy_from, copy_to, model_name = nil, type_cast_functions = {}) ⇒ CopyColumn
constructor
A new instance of CopyColumn.
- #process(relation) ⇒ Object
Methods inherited from DataMigration
#after_cancel, #after_complete, #after_pause, #after_resume, #after_start, #after_stop, #around_process, #build_enumerator, collection_batch_size, named
Constructor Details
#initialize(table_name, copy_from, copy_to, model_name = nil, type_cast_functions = {}) ⇒ CopyColumn
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 9 def initialize(table_name, copy_from, copy_to, model_name = nil, type_cast_functions = {}) @table_name = table_name if copy_from.is_a?(Array) && type_cast_functions && !type_cast_functions.is_a?(Hash) raise ArgumentError, "type_cast_functions must be a Hash" end @copy_from = Array.wrap(copy_from) @copy_to = Array.wrap(copy_to) if @copy_from.size != @copy_to.size raise ArgumentError, "Number of source and destination columns must match" end @model_name = model_name @model = if model_name.present? Object.const_get(model_name, false) else Utils.define_model(table_name) end @type_cast_functions = type_cast_functions end |
Instance Attribute Details
#copy_from ⇒ Object (readonly)
Returns the value of attribute copy_from.
7 8 9 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 7 def copy_from @copy_from end |
#copy_to ⇒ Object (readonly)
Returns the value of attribute copy_to.
7 8 9 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 7 def copy_to @copy_to end |
#model_name ⇒ Object (readonly)
Returns the value of attribute model_name.
7 8 9 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 7 def model_name @model_name end |
#table_name ⇒ Object (readonly)
Returns the value of attribute table_name.
7 8 9 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 7 def table_name @table_name end |
#type_cast_functions ⇒ Object (readonly)
Returns the value of attribute type_cast_functions.
7 8 9 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 7 def type_cast_functions @type_cast_functions end |
Instance Method Details
#collection ⇒ Object
34 35 36 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 34 def collection @model.unscoped.in_batches(of: 100, use_ranges: true) end |
#count ⇒ Object
59 60 61 62 63 64 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 59 def count # Exact counts are expensive on large tables, since PostgreSQL # needs to do a full scan. An estimated count should give a pretty decent # approximation of rows count in this case. Utils.estimated_count(@model.connection, table_name) end |
#process(relation) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/online_migrations/background_data_migrations/copy_column.rb', line 38 def process(relation) arel_table = relation.arel_table old_values = copy_from.map do |from_column| old_value = arel_table[from_column] if (type_cast_function = type_cast_functions[from_column]) old_value = if type_cast_function.match?(/\A\w+\z/) Arel::Nodes::NamedFunction.new(type_cast_function, [old_value]) else # We got a cast expression. Arel.sql(type_cast_function) end end old_value end updates = copy_to.zip(old_values).to_h { |to_column, old_value| [to_column, old_value] } relation.update_all(updates) end |