Class: RuboCop::Cop::Migration::ChangeTableReferences

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/migration/change_table_references.rb

Overview

Prevent using t.references or t.belongs_to in a change_table. Internally, t.references use multiple ALTER TABLE statements. Since Rails cannot transform automatically t.references inside a change_table bulk: true we can manually create the equivalent ALTER TABLE statement using t.bigint, t.index and t.foreign_key.

#bad
change_table :subscriptions, bulk: true do |t|
t.references :user, null: false, foreign_key: true
end

#good
change_table :subscriptions, bulk: true do |t|
t.bigint :user_id, null: false
t.index :user_id
t.foreign_key :users, column: :user_id
end

Constant Summary collapse

MSG =
'Use a combination of `t.bigint`, `t.index` and `t.foreign_key` in a change_table to add a reference.' \
'Or `t.remove_foreign_key`, `t.remove` to remove a reference.'

Instance Method Summary collapse

Instance Method Details

#add_references_in_block?(node) ⇒ Object



28
29
30
# File 'lib/rubocop/cop/migration/change_table_references.rb', line 28

def_node_matcher :add_references_in_block?, "(send lvar /references|belongs_to|remove_references|remove_belongs_to/ ...)\n"

#change_table?(node) ⇒ Object



33
34
35
# File 'lib/rubocop/cop/migration/change_table_references.rb', line 33

def_node_matcher :change_table?, "(block (send nil? :change_table ...) ...)\n"

#on_block(node) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/rubocop/cop/migration/change_table_references.rb', line 37

def on_block(node)
  return unless change_table?(node)

  references_node = node.child_nodes[2].each_node.detect { |n| add_references_in_block?(n) }
  return unless references_node

  arguments = references_node.child_nodes[1]
  references_methods_range = references_node.source_range.with(end_pos: arguments.source_range.begin_pos - 1)
  add_offense(references_methods_range)
end