← Back to Upcase

Adding alias_attribute in a migration?


(Jon Seidel) #1

I need to replace a column in my user model with an alias_attribute; e.g., what used to be a column named ‘email’ needs to be replaced with:

  alias_attribute :email, :emailaddr

Is there any way to do this in a migration, or do I just have to run a migration to remove the email column and then modify my User model manually? I suppose I could add a simple sed command to add/remove the alias_attribute line in the model so that my migration is reversible, but I wonder if there’s a better way…


(Derek Prior) #2

The migration (change_column, I presume) should be reversible regardless of what is in your model. Your tests might fail if you reverse/apply a migration and do nothing else, but… don’t do that. Reverse the migration and then revert your commit (which had the migration and the change to your model) if you need to.


(Jon Seidel) #3

I agree that’s the goal, and using sed is how I got it all to work. This migration does what I want and is reversible:

class AddAliasToUser < ActiveRecord::Migration

  def up
    remove_column :users, :email
    cmd = <<-EOF
    sed -e '/include Clearance::User/a\
      alias_attribute :email, :emailaddr\' -i.bak app/models/user.rb
      EOF
    ret = system(cmd)
  end 
  def down
    add_column :users, :email, :string
    cmd = <<-EOF
    sed -e '/alias_attribute :email/d' -i.bak app/models/user.rb
    EOF
    ret = system(cmd)
  end 
end

And the alias works just fine


(Derek Prior) #4

You definitely do not want to use migrations in this manner.

Migrations are for updating your database schema, not for altering your classes. There are any number of things that can go wrong if you continue to do this. What if at some point, you replace your simple attribute with an actual method? What will this do to your migration? What happens when you deploy to an environment that doesn’t want to let your write to your app directory (e.g. heroku)?

Make your schema change in your migration. Make your class change in that class. Commit both. To revert that change, reverse the migration the rollback your commit. Your git history manages changes to your class, not migrations.