Migration fails in production, but ran as expected in development.
... # everything to
20120709174326_add_subject_to_campaigns.rb # here runs fine.
20120711001125_set_default_value_for_publishable_in_newsletter.rb # <- this fails.
20120711010818_set_default_value_for_publishable_in_contents.rb
20120711010855_set_default_value_for_published_in_editions.rb
20120711191427_add_newsletter_date_to_newsletters.rb
20120711194230_rename_cm_campaign_sent_at_in_campaigns.rb
The migration error looks like this:
-bash> heroku run rake db:migrate --remote staging
Running rake db:migrate attached to terminal... up, run.1
== SetDefaultValueForPublishableInNewsletter: migrating ======================
-- change_column(:newsletters, :publishable, :boolean, {:default=>false})
-> 0.1554s
rake aborted!
An error has occurred, this and all later migrations canceled:
undefined method `newsletter_date' for #<Newsletter:0x00000005961bd0>
The thing is, newsletter_date is not added till later, so why is it failing / mentioning it so soon? It ran perfectly fine in development.
It turns out that the failing migration (
20120711001125_set_default_value_for_publishable_in_newsletter.rb) …… uses the model
Newsletter, and runs validations before saving (specifically, thepresencevalidation onnewsletter_date) …… but
newsletter_datedoes not exist yet, because it (thenewsletter_datecolumn) is not added till later (20120711191427_add_newsletter_date_to_newsletters.rb— the second-last migration in the list above):The solution is: (1) in development, rollback the migrations to the one before the failing one; (2) rename the migration that adds the column, changing its timestamp to just prior to the failing migration; (3) run the migrations; (4) update git; (5) push to Heroku; (6) in production, run the migrations; (7) restart the Heroku processes.
The reason it worked in development is because at the time the migration that set the default value for the
publishablecolumn in thenewsletterstable ran, thenewsletter_datecolumn and model validation did not yet exist, so it was not a problem. By the time it all went out to production, the more recent code brought thenewsletter_datemethod and related validation into existence, but since migrations run on existing code in order of timestamps, newer code may exist than the database is prepared for.