Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Rails Migrations be used to convert data?

I'm trying to convert a column in my Rails app, for arguments sake let's pretend I'm trying to change the age column in my users table to a string representation rather than an int.

In my migration I have this;

def.self up     add_column :users, :age_text, :string      users = User.find(:all)      users.each do |u|        u.age_text = convert_to_text(u.age)        u.save     end end  def self.convert_to_text(number)    #code here to convert 1 to 'one' etc end 

But it doesn't seem to be working, is what I'm attempting here even possible with migrations?

like image 203
Kirschstein Avatar asked May 11 '09 20:05

Kirschstein


People also ask

What can Rails migration do?

A Rails migration is a tool for changing an application's database schema. Instead of managing SQL scripts, you define database changes in a domain-specific language (DSL). The code is database-independent, so you can easily move your app to a new platform.

Why do we need migration in Rails?

Migrations are a convenient way to alter your database schema over time in a consistent way. They use a Ruby DSL so that you don't have to write SQL by hand, allowing your schema and changes to be database independent. You can think of each migration as being a new 'version' of the database.

How Rails db Migrate works?

When you run db:migrate, rails will check a special table in the database which contains the timestamp of the last migration applied to the database. It will then apply all of the migrations with timestamps after that date and update the database table with the timestamp of the last migration.

Are Rails migrations run in a transaction?

On databases that support transactions with statements that change the schema, migrations are wrapped in a transaction. If the database does not support this then when a migration fails the parts of it that succeeded will not be rolled back. You will have to rollback the changes that were made by hand.


2 Answers

What you're trying to do is possible, and I would say the correct thing to do.

You need, though, to reload the column info for the model classes you're updating in the migration, so that Rails knows about the new columns. Try this:

def.self up     add_column :users, :age_text, :string      User.reset_column_information       users = User.find(:all)      users.each do |u|        u.age_text = convert_to_text(u.age)        u.save     end end 

On a separate note, please note that if your table is large, doing updates one by one will take a looong time.. Be careful with that.

like image 81
Eduardo Scoz Avatar answered Oct 02 '22 15:10

Eduardo Scoz


Since I'm new here I can't comment on the above so I'll add my own answer.

GENERALLY manipulating data in migrations is a BAD idea. Migrations with direct model access can get stuck if the model logic changes.

Imagine in your second migration you've added a new column. You want to seed that column with new data.

Let's also say a few weeks later you add a new validation to the model - a validation that operates on a field that does not yet exist in your second migration. if you ever were to construct the database from migration 0, you'd have some problems.

I strongly suggest using migrations to alter columns and other means to manage database data, especially when moving to production.

like image 38
Brian Hogan Avatar answered Oct 02 '22 14:10

Brian Hogan