Мне очень нравятся миграции в стиле Rails 3, то есть одно изменение
метод достаточно умен, чтобы распознать, устанавливаются ли миграции или откатываются, поэтому мне не нужно писать методы вверх
и вниз
, зеркально отражающие друг друга. Но у меня есть ситуация, когда мне нужно пропустить некоторый код при откате миграции (обновление столбцов counter_cache
, которые я добавляю).
Я просмотрел http://guides.rubyonrails.org/migrations.html , но примеры в конце раздела 5 страдают той же проблемой:
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
Когда эта миграция откатывается, обновление поля fuzz
не требуется. Есть ли способ предотвратить это?
Я попытался заглянуть в Product.column_names
, но поскольку Rails достаточно умен, чтобы выполнять миграцию в обратном направлении, обновление выполняется до удаления столбца. Кроме того, когда определен метод change
, любые методы вверх
или вниз
игнорируются. Есть еще идеи?
В этом случае, я думаю, вам придется использовать методы up
и down
как обычно. Не волнуйтесь, несмотря на добавление change
в Rails 3, эти методы, насколько я знаю, не привязаны к блоку прерывания. Продолжайте использовать их там, где это необходимо.
Редактировать: Вот вариант: переопределить migrate
.
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
end
def migrate(direction)
super # Let Rails do its thing as usual...
if direction == :up # ...but then do something extra if we're going 'up.'
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
end
Мысли?
В рельсах 3.x вы также можете сделать это
class AddFuzzToProduct < ActiveRecord::Migration
class Product < ActiveRecord::Base
end
def change
add_column :products, :fuzz, :string
unless reverting?
# Do this only when direction is up
Product.reset_column_information
Product.all.each { |f| f.update_attributes! :fuzz => 'fuzzy' }
end
end
end