Sunday
May 27, 2012
by cantbecool at 06:18PM

How does Rails know if a migration has previously run? I ran this question by a few colleagues at my nine-to-five yesterday, and they all were uncertain on how Rails achieved it. We all thought that the schema.rb file associated to your project had something to do with it; however, we were mistaken, and it does not. The schema.rb is for constructing a new database from scratch, or for an existing project to know the up-to-date version of your Rails application’s database schema. At my place of employment, we use the schema.rb to deploy new servers that run our application without having to invoke all of the active record migrations associated our project; doing so would take too much time and potentially cause errors that would render the database unusable.

Now back to the original question. I checked Rails Guides, but they only presented me with vague information regarding it. So I turned to Stack Overflow, which led me in the right direction.

Rails determines what active record migrations has been previously run by the hidden table that all Ruby on Rails projects have in their database schema: schema_migrations. schema_migrations contains a single column named “version”. In that column it contains the timestamps that are preappended to the name of your migrations that you have created, i.e., 20110705043737, which is attached to a migration that this weblog previously ran 20110705043737_create_posts.rb. Each timestamp in schema_migration version column represents migrations that have previously invoked. Below you can see the migrations that have invoked for the weblog you are currently reading.

Output below is from the postgres console:

select * from schema_migrations;

    version     
----------------
 20110623095018 
 20110628001857 
 20110702042423 
 20110705042856 
 20110705043737 
(5 rows)

To illustrate, imagine you have created a migration to add a column to table called “20120526043737_add_hyperlink_to_pages.rb” and execute rake db:migrate in the terminal. Rails will search for the time stamp 20120526043737 in schema_migrations; not find a version with an identical time stamp; execute the migration which adds hyperlink to pages; add that time stamp to schema_migrations so the next time you run rake db:migrate it will not execute that migration again, and then finally update your applications schema.rb, which makes it up to date. On the opposite end of the spectrum, imagine if Rails found the migration time stamp in schema_migrations; it would not invoke the migration and move on the next migration, if there is one.

Hopefully, this post gets properly indexed by Google and is beneficial to someone who wonders how Ruby on Rails Active Record magic works.


Drakenhoff

As far as I know, it just issues an alter chnage command on the database. So I guess it depends on what RDBMS you are using and how it reacts to alter table chnage . For instance, if you are using mysql it would issue this command to your database:ALTER TABLE widgets CHANGE count count float;In this case there would be no data loss since its converting from int to float, but if you were converting a text type to string you would lose data. So it may be desirable to perform some data manipulation on the data before/after you run the migration, depending on what your scenario is.To find the column type, you can use this:Widget.columns_hash["id"].sql_type #=> "integer"
Posted at July 23, 2012 14:43

cantbecool

Thanks for the insight, Drakenhoff. I didn't know about that.
Posted at August 07, 2012 02:36