class RuboCop::Cop::Rails::ReversibleMigration

@see api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html<br><br>end
end
end
end
t.change :price, :integer
dir.down do
end
t.change :price, :string
dir.up do
change_table :users do |t|
reversible do |dir|
def change
# good
end
end
t.string :name
change_table :users do |t|
def change
# good
end
end
t.change :price, :string
t.change_default :authorized, 1
t.remove :name
change_table :users do |t|
def change
# bad
# change_table
@example
end
remove_foreign_key :accounts, :branches
def change
# good
end
remove_foreign_key :accounts, column: :owner_id
def change
# bad
# remove_foreign_key
@example
end
remove_column(:suppliers, :qualification, :string)
def change
# good
end
remove_column(:suppliers, :qualification)
def change
# bad
# remove_column
@example
end
change_column_default(:posts, :state, from: nil, to: “draft”)
def change
# good
end
change_column_default(:suppliers, :qualification, ‘new’)
def change
# bad
# change_column_default
@example
end
end
t.string :name
drop_table :users do |t|
def change
# good
end
drop_table :users
def change
# bad
# drop_table
@example
end
end
end
end
t.remove :name
dir.down do
end
t.column :name, :string
dir.up do
change_table :users do |t|
reversible do |dir|
def change
# good
end
end
t.string :name
create_table :users do |t|
def change
# good
end
end
t.remove :name
change_table :users do |t|
def change
# bad
@example
reversible.
This cop checks whether the change method of the migration file is

def all_hash_key?(args, *keys)

def all_hash_key?(args, *keys)
  return false unless args && args.hash_type?
  hash_keys = args.to_a.map do |arg|
    arg.to_a.first.children.first.to_sym
  end
  hash_keys & keys == keys
end

def check_change_column_default_node(node)

def check_change_column_default_node(node)
  change_column_default_call(node) do |args|
    unless all_hash_key?(args.first, :from, :to)
      add_offense(
        node, :expression,
        format(MSG, 'change_column_default(without :from and :to)')
      )
    end
  end
end

def check_change_table_node(node, block)

def check_change_table_node(node, block)
  change_table_call(node) do |arg|
    if target_rails_version < 4.0
      add_offense(
        node, :expression,
        format(MSG, 'change_table')
      )
    elsif block.send_type?
      check_change_table_offense(arg, block)
    else
      block.each_child_node do |child_node|
        check_change_table_offense(arg, child_node)
      end
    end
  end
end

def check_change_table_offense(receiver, node)

def check_change_table_offense(receiver, node)
  method_name = node.method_name
  return if receiver != node.receiver &&
            !IRREVERSIBLE_CHANGE_TABLE_CALLS.include?(method_name)
  add_offense(
    node, :expression,
    format(MSG, "change_table(with #{method_name})")
  )
end

def check_drop_table_node(node)

def check_drop_table_node(node)
  drop_table_call(node) do
    unless node.parent.block_type?
      add_offense(
        node, :expression,
        format(MSG, 'drop_table(without block)')
      )
    end
  end
end

def check_irreversible_schema_statement_node(node)

def check_irreversible_schema_statement_node(node)
  irreversible_schema_statement_call(node) do |method_name|
    add_offense(node, :expression, format(MSG, method_name))
  end
end

def check_remove_column_node(node)

def check_remove_column_node(node)
  remove_column_call(node) do |args|
    if args.to_a.size < 3
      add_offense(
        node, :expression,
        format(MSG, 'remove_column(without type)')
      )
    end
  end
end

def check_remove_foreign_key_node(node)

def check_remove_foreign_key_node(node)
  remove_foreign_key_call(node) do |arg|
    if arg.hash_type?
      add_offense(
        node, :expression,
        format(MSG, 'remove_foreign_key(without table)')
      )
    end
  end
end

def on_block(node)

def on_block(node)
  return unless within_change_method?(node)
  return if within_reversible_block?(node)
  check_change_table_node(node.send_node, node.body)
end

def on_send(node)

def on_send(node)
  return unless within_change_method?(node)
  return if within_reversible_block?(node)
  check_irreversible_schema_statement_node(node)
  check_drop_table_node(node)
  check_change_column_default_node(node)
  check_remove_column_node(node)
  check_remove_foreign_key_node(node)
end

def within_change_method?(node)

def within_change_method?(node)
  node.each_ancestor(:def).any? do |ancestor|
    method_name, = *ancestor
    method_name == :change
  end
end

def within_reversible_block?(node)

def within_reversible_block?(node)
  node.each_ancestor(:block).any? do |ancestor|
    ancestor.block_type? && ancestor.send_node.method?(:reversible)
  end
end