Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update one column to value of another in Rails migration

I have a table in a Rails app with hundreds of thousands of records, and they only have a created_at timestamp. I'm adding the ability to edit these records, so I want to add an updated_at timestamp to the table. In my migration to add the column, I want to update all rows to have the new updated_at match the old created_at, since that's the default for newly created rows in Rails. I could do a find(:all) and iterate through the records, but that would take hours because of the size of the table. What I really want to do is:

UPDATE table_name SET updated_at = created_at; 

Is there a nicer way to do that in a Rails migration using ActiveRecord rather than executing raw SQL?

like image 778
jrdioko Avatar asked Mar 07 '11 20:03

jrdioko


People also ask

Can you edit a migration file rails?

Occasionally you will make a mistake when writing a migration. If you have already run the migration then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run rake db:migrate.

How do I migrate a specific migration in rails?

To run a specific migration up or down, use db:migrate:up or db:migrate:down . The version number in the above commands is the numeric prefix in the migration's filename. For example, to migrate to the migration 20160515085959_add_name_to_users. rb , you would use 20160515085959 as the version number.


2 Answers

I would create a migration

rails g migration set_updated_at_values 

and inside it write something like:

class SetUpdatedAt < ActiveRecord::Migration   def self.up     Yourmodel.update_all("updated_at=created_at")   end    def self.down   end end 

This way you achieve two things

  • this is a repeatable process, with each possible deploy (where needed) it is executed
  • this is efficient. I can't think of a more rubyesque solution (that is as efficient).

Note: you could also run raw sql inside a migration, if the query gets too hard to write using activerecord. Just write the following:

Yourmodel.connection.execute("update your_models set ... <complicated query> ...") 
like image 80
nathanvda Avatar answered Sep 20 '22 22:09

nathanvda


You can use update_all which works very similar to raw SQL. That's all options you have.

BTW personally I do not pay that much attention to migrations. Sometimes raw SQL is really best solution. Generally migrations code isn't reused. This is one time action so I don't bother about code purity.

like image 30
Greg Dan Avatar answered Sep 16 '22 22:09

Greg Dan