How do you write a migration to rename an ActiveRecord model and its table in Rails? How do you write a migration to rename an ActiveRecord model and its table in Rails? ruby-on-rails ruby-on-rails

How do you write a migration to rename an ActiveRecord model and its table in Rails?


Here's an example:

class RenameOldTableToNewTable < ActiveRecord::Migration  def self.up    rename_table :old_table_name, :new_table_name  end  def self.down    rename_table :new_table_name, :old_table_name  endend

I had to go and rename the model declaration file manually.

Edit:

In Rails 3.1 & 4, ActiveRecord::Migration::CommandRecorder knows how to reverse rename_table migrations, so you can do this:

class RenameOldTableToNewTable < ActiveRecord::Migration  def change    rename_table :old_table_name, :new_table_name  end end

(You still have to go through and manually rename your files.)


In Rails 4 all I had to do was the def change

def change  rename_table :old_table_name, :new_table_nameend

And all of my indexes were taken care of for me. I did not need to manually update the indexes by removing the old ones and adding new ones.

And it works using the change for going up or down in regards to the indexes as well.


The other answers and comments covered table renaming, file renaming, and grepping through your code.

I'd like to add a few more caveats:

Let's use a real-world example I faced today: renaming a model from 'Merchant' to 'Business.'

  • Don't forget to change the names of dependent tables and models inthe same migration. I changed my Merchant and MerchantStat models to Business and BusinessStat at the same time. Otherwise I'd have had to do way too much picking and choosing when performing search-and-replace.
  • For any other models that depend on your model via foreign keys, the other tables' foreign-key column names will be derived from your original model name. So you'll also want to do some rename_column calls on these dependent models. For instance, I had to rename the 'merchant_id' column to 'business_id' in various join tables (for has_and_belongs_to_many relationship) and other dependent tables (for normal has_one and has_many relationships). Otherwise I would have ended up with columns like 'business_stat.merchant_id' pointing to 'business.id'. Here's a good answer about doing column renames.
  • When grepping, remember to search for singular, plural, capitalized,lowercase, and even UPPERCASE (which may occur in comments) versionsof your strings.
  • It's best to search for plural versions first, then singular. Thatway if you have an irregular plural - such as in my merchants ::businesses example - you can get all the irregular plurals correct.Otherwise you may end up with, for example, 'businesss' (3 s's) as anintermediate state, resulting in yet more search-and-replace.
  • Don't blindly replace every occurrence. If your model names collidewith common programming terms, with values in other models, or withtextual content in your views, you may end up being too over-eager.In my example, I wanted to change my model name to 'Business' butstill refer to them as 'merchants' in the content in my UI. I also had a 'merchant' role for my users in CanCan - it was the confusion between the merchant role and the Merchant model that caused me to rename the model in the first place.