Posted almost 5 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. :)

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Arne Hartherz
Last edit:
about 1 year 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