Posted about 4 years ago. Visible to the public. Repeats.

How to combine "change", "up", and "down" in a Rails migration

Rails migrations allow you to use a change method whose calls are automatically inverted for the down path. However, if you need to some path-specific logic (like SQL UPDATE statements) you can not define up and down methods at the same time.

If you were to define define all 3 of them, Rails would only run change and ignore up and down. However, Rails 4+ features a helper method called reversible:

class MyMigration < ActiveRecord::Migration def change rename_table :old_table, :new_table rename_index ... rename_column ... add_column ... ... reversible do |change| change.up do update "UPDATE new_table SET foo = something_really_complex" end change.down do update "UPDATE new_table SET foo = what_it_was_before" end end end end

Note that the "down" path is like running the change block from bottom upwards.

This is relevant when writing SQL statements: When migrating down, the rename_table statement will be run after the reversible block. While this makes sense, it may feel odd that the SQL statement says "UPDATE new_table".

If your migration becomes too complex, you could put your logic into multiple reversible blocks (so they contain only one of up/down).

Rails 3

If you are on Rails 3, you can use this:

class MyMigration < ActiveRecord::Migration def up make_changes update "UPDATE new_table SET foo = something_really_complex" end def down revert { make_changes } update "UPDATE old_table SET bar = something_different" end private def make_changes # Rails can guess the inverse calls of these rename_table :old_table, :new_table rename_index ... rename_column ... add_column ... ... end end

Notice how we defined make_changes to behave like change. Using revert does all the magic we need, so we use that in our down path.

Remember: depending on your migration you might be better off just defining 2 separate paths up and down instead. :)

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Arne Hartherz
Last edit:
5 months ago
by Tobias Kraze
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more