Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3: Migrate data

My Rails 3 app has a User model and a Profile model. A User has_one Profile.

Currently the Profile has attributes first_name and last_name. While I'm not sure why you might want to change them, I originally imagined these should be changeable and so I put them in the Profile model instead of the User model.

However, as the app has evolved I have found that in fact I need the user's first and last name not to be changed, and that I really need them to be part of the User model instead of the profile model.

So, I was wondering, can you write a migration that would:

  1. Add the first_name and last_name columns to the User model.
  2. Take the existing first_name and last_name value for a given user from the associated Profile record and copy it into the User model.
  3. Remove the first_name and last_name columns from the Profile model since they wouldn't be needed anymore.

So, can this be done? Could you show an example? And, most importantly, are there any gotchas I should be aware of? I'd like to apply this change to a production app so it's critical that I don't lose data when I make this change.

Thanks!

like image 878
Andrew Avatar asked Dec 05 '22 22:12

Andrew


1 Answers

Sure, very easy. Put this in a migration:

    add_column(:users, :last_name, :string)
    add_column(:users, :first_name, :string)

    User.reset_column_information

    User.all.each do |u|
      u.last_name = u.profile.try(:last_name)
      u.first_name = u.profile.try(:first_name)
      u.save
    end

    remove_column(:profiles, :first_name)
    remove_column(:profiles, :last_name)

I used try() there to mitigate against the possibility of a missing profile. It's not checking for errors on the save operation, so take that into account if you think it needs to. Also, as always, do a database dump backup before you run it. :)

like image 187
DGM Avatar answered Jan 01 '23 04:01

DGM