I really like the Rails 3 style migrations, i.e. one change
method being smart enough to recognize if the migrations is being installed or rolled back, so I don't have to write up
and down
methods mirroring each other. But I have situation that I need to skip some code when the migration is rolled back (updating counter_cache
columns that I'm adding).
I looked at http://guides.rubyonrails.org/migrations.html but the examples at the end of section 5 suffer from the same problem:
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
When this migration is rolled back, the update of fuzz
field is unnecessary. Is there a way to prevent it?
I tried looking into Product.column_names
but since Rails is smart enough to perform migration in reverse direction, the update is executed before the column is removed. Also, when change
method is defined, any up
or down
methods seem to be ignored. Any other ideas?
When you run rails db:migrate, the up method is executed, whereas rails db:rollback executes the down method. Simply, up runs the migration, down rolls the migration back.
If you need a bash one-liner to determine whether to run a migration or not (e.g., only migrate in a Heroku release phase command when there is a pending migration), this works: (rails db:migrate:status | grep "^\s*down") && rails db:migrate || echo "No pending migrations found."
To check for status, run rails db:migrate:status . Then you'll have a good view of the migrations you want to remove. Then, run rails db:rollback to revert the changes one by one. After doing so, you can check the status again to be fully confident.
A Rails migration is a tool for changing an application's database schema. Instead of managing SQL scripts, you define database changes in a domain-specific language (DSL). The code is database-independent, so you can easily move your app to a new platform.
Just for future reference, for Rails 4 the best way to do this is to use reversible:
def change # ...change code... reversible do |dir| dir.up do # ...up-only code... end end end
See http://guides.rubyonrails.org/migrations.html#using-reversible
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With