Подтвердить что ты не робот

Как вы делаете remove_column обратимым?

У меня есть миграция, которая удаляет столбец:

def change
  remove_column :foos, :bar, :boolean
end

Когда я пытаюсь выполнить rake db:rollback этот перенос, я получаю следующую ошибку:

remove_column is only reversible if given a type.

В документации ActiveRecord:: Migration указано, что следующая подпись - это remove_column:

remove_column(table_name, column_name, type, options)

Итак, мой тип в этом случае должен быть :boolean, и я ожидаю, что миграция будет обратимой. Что мне не хватает?

Я могу, конечно, разбить это на миграции up и down, чтобы избежать этой проблемы, но я хотел бы понять, почему синтаксис change не работает в этом случае.

4b9b3361

Ответ 1

Просто добавление третьего аргумента (тип column: type) к методу remove_column делает миграцию обратимой. Таким образом, исходный код OP действительно работал, как в:

remove_column :foos, :bar, :boolean

Остальная часть этого ответа была попыткой выяснить, почему этот метод не работал, но OP в конечном итоге заставил его работать.


Я вижу несколько противоположную информацию в документации для ActiveRecord:: Migration:

Некоторые команды, такие как remove_column, не могут быть отменены. Если вы хотите определить, как двигаться вверх и вниз в этих случаях, вы должны определить методы вверх и вниз, как раньше.

Список команд, которые обратимы, см. в разделе ActiveRecord:: Migration:: CommandRecorder.

И это из ActiveRecord:: Migration:: CommandRecorder:

ActiveRecord:: Migration:: CommandRecorder записывает команды, выполненные во время миграции, и знает, как отменить эти команды. CommandRecorder знает, как инвертировать следующие команды:

add_column

add_index

add_timestamps

create_table

create_join_table

remove_timestamps

rename_column

rename_index

rename_table

В любом случае, похоже, что эта документация устарела... Копаем в источник в github:

Метод, который дает вам печаль:

def invert_remove_column(args)
  raise ActiveRecord::IrreversibleMigration, "remove_column is only reversible if given a type." if args.size <= 2
  super
end

Я дал этот снимок... настроил миграцию в моем приложении Rails 4.1.2, и миграция работала в обоих направлениях - вверх и вниз. Вот моя миграция:

class TestRemoveColumn < ActiveRecord::Migration
  def change
    remove_column :contacts, :test, :boolean
  end
end

Я также пробовал с отсутствующим аргументом :boolean и получил ту же ошибку, о которой вы говорите. Вы уверены, что находитесь в финальной версии Rails 4.1.2 - не один из кандидатов на выпуск? Если да, я предлагаю положить binding.pry в источник Rails для метода invert_remove_column, чтобы проверить список аргументов и посмотреть, что происходит. Для этого просто запустите bundle open activerecord, а затем выполните поиск: lib/active_record/migration/command_recorder.rb: 128.

Ответ 2

Вместо использования change вы используете методы up и down для миграции:

def up
  remove_column :foos, :bar
end

def down
  add_column :foos, :bar, :boolean
end