I have a migration that saves correctly to the database when it's run
by itself through db:migrate:up, but not when it's run with other
migrations through db:migrate.
class SetActiveOnExistingItems < ActiveRecord::Migration
def self.up
Item.all.each do |item|
if item.item_status == Item::STATUS_REVIEW
item.active = false
elsif item.item_status == Item::STATUS_IN_PROGRESS
item.active = false
else
item.active = true
end
puts "setting item_id = #{item.id} to active = #{item.active}"
item.save!
puts "setting item_id = #{item.id} to active = #{item.active}"
item = Item.find(item.id)
puts "setting item_id = #{item.id} to active = #{item.active}"
end
end
def self.down
Item.all.each {|item| item.active = nil; item.save(false)}
end
end
The output during db:migrate is:
setting item_id = 1 to active = true # (this one is before the save)
setting item_id = 1 to active = true # (this one is after the save)
setting item_id = 1 to active = # (this one is after the lookup)
...
During db:migrate:up, it works as expected:
setting item_id = 1 to active = true
setting item_id = 1 to active = true
setting item_id = 1 to active = true
...
For some reason, the data appears to not be actually committed to the
database during db:migrate, while it is during db:migrate:up. There's
no exception thrown by save!, no indicator that I can see that the
save is unsuccessful. Even if it was, why would it only be
unsuccessful during a regular migration run, and not during
db:migrate:up?
Has anyone seen this before? Do you have any idea what could cause
this?
Sorry, I should have mentioned - the migration before it is one where
that active column is added. The migration after alters a column in a
different table. The column is definitely added before this migration
runs.
Oh also "Item.reset_column_information" needs to be after the
add_column and before the Item.all.each if you are adding the column
and manipulating the data in the same migration. If it is 2 separate
migrations, just put it at the top of the 2nd one.
You should also be careful about using model classes in migrations -
because your source is updated in one go but migrations run one by one
it's easy enough to run into trouble. For example if your model has a
validation on a column that is added by migration two and migration
one tries to create some objects of that class then it will fail
because of the validation on the not yet existent column
Sure enough, I see that exact information in the Migration documentation.ActiveRecord::Migration
It works great now. Thank you.
You should also be careful about using model classes in migrations -
because your source is updated in one go but migrations run one by one
it's easy enough to run into trouble. For example if your model has a
validation on a column that is added by migration two and migration
one tries to create some objects of that class then it will fail
because of the validation on the not yet existent column
And this is why it's now considered preferable to use rake
db:schema:load when setting up a server from scratch. Migrations are
primarily for migration