Last Updated: February 25, 2016
·
5.323K
· yan-foto

Using Models in Rails Migrations

Every now and then one is tempted to use models in rails migrations. This ingenious idea, however, turns out to be a pitfall since the life cycle of the code (model in this case) does not necessarily match that of the migrations. An example is given by Rails Guide showing how to create a local model within the migration to avoid such conflicts.

Another example would be renaming a models name (e.g. from class Item < ActiveRecord::Base to class Product < ActiveRecord::Base) and its corresponding table. This would break all the previous migrations utilizing that model. For example following migration would break:

class SomeMigration < ActiveRecord::Migration
  method def
    items = Item.all
    ...
  end
end

Note that at this point the table items already exists (since the new migration, which changes its name has naturally a bigger timestamp and is to be run after this migration) and using pure SQL (or respective DB DSL) using execute (as some may propose) can save all such migrations from breaking:

class SomeMigration < ActiveRecord::Migration
  method def
    execute << -SQL
      ...
      SELECT "items".* FROM "items"
      ...
    SQL
  end
end

This, however, creates a new problem:

  • Switching to another DB (e.g. MySQL to PostgreSQL) demands rewriting all migrations including such codes. In other words the system is not DB agnostic anymore
  • The convenient Active Record Query Interface (e.g. ActiveRecord.find)cannot be used anymore.

The best solution (that I have found up to now) is to create a generic model in the migration and make it access a specific table:

class SomeMigration < ActiveRecord::Migration

    class GenericModel < ActiveRecord::Base
      self.table_name = 'items'
    end

  method def
      GenericModel.find ...
      ...
  end
end

This way we can conserve the DB agnostic feature of RoR and enjoy the rich query interface without fearing future modifications to the model.


Disclaimer: This solution is a modified version of "How to use models in your migrations (without killing kittens)"