Class: OnlineMigrations::BackgroundMigrations::CopyColumn

Inherits:
OnlineMigrations::BackgroundMigration show all
Defined in:
lib/online_migrations/background_migrations/copy_column.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from OnlineMigrations::BackgroundMigration

named

Constructor Details

#initialize(table_name, copy_from, copy_to, model_name = nil, type_cast_functions = {}) ⇒ CopyColumn

Returns a new instance of CopyColumn.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/online_migrations/background_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
  @type_cast_functions = type_cast_functions
end

Instance Attribute Details

#copy_fromObject (readonly)

Returns the value of attribute copy_from.



7
8
9
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 7

def copy_from
  @copy_from
end

#copy_toObject (readonly)

Returns the value of attribute copy_to.



7
8
9
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 7

def copy_to
  @copy_to
end

#model_nameObject (readonly)

Returns the value of attribute model_name.



7
8
9
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 7

def model_name
  @model_name
end

#table_nameObject (readonly)

Returns the value of attribute table_name.



7
8
9
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 7

def table_name
  @table_name
end

#type_cast_functionsObject (readonly)

Returns the value of attribute type_cast_functions.



7
8
9
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 7

def type_cast_functions
  @type_cast_functions
end

Instance Method Details

#countObject



59
60
61
62
63
64
# File 'lib/online_migrations/background_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(connection, table_name)
end

#process_batch(relation) ⇒ Object



31
32
33
34
35
36
37
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_migrations/copy_column.rb', line 31

def process_batch(relation)
  arel = relation.arel
  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

  stmt = Arel::UpdateManager.new
  stmt.table(arel_table)
  stmt.wheres = arel.constraints

  updates = copy_to.zip(old_values).map { |to_column, old_value| [arel_table[to_column], old_value] }
  stmt.set(updates)

  connection.update(stmt)
end

#relationObject



27
28
29
# File 'lib/online_migrations/background_migrations/copy_column.rb', line 27

def relation
  model.unscoped
end