How to make rails migrations pretty
I have seen a lot of migrations, most of them was just doing what it had to do. But I found a nice way to make my migrations more pretty.
So I had an Article model, which had field :published of type :boolean , as comparing to other solutions, I found that it should be rather :publish_date of type date.
First I have created migration using “script/generate migration article_update” and got empty migration:
class UpdateArticles < ActiveRecord::Migration def self.up end def self.down end end [/sourcecode] To be able to freely play with Fields we add our private implementation of article model, we change the fields and move data for them: [sourcecode language='ruby'] class UpdateArticles < ActiveRecord::Migration class Article < ActiveRecord::Base; end def self.up add_column :articles, :publish_date, :datetime, :null => true Article.reset_column_information Article.all.each { |article| article.update_attribute(:publish_date, :created_at) if article.publish } remove_column :articles, :publish end def self.down add_column :articles, :publish, :boolean Article.reset_column_information Article.all.each { |article| article.update_attribute(:publish, true) unless article.publish_date.nil? } remove_column :articles, :publish_date end end
But this is not really what we wanted, if we have already a lot of data in Article tables then we will not know what is going on during update attribute action.
To make it display pretty we have to add say_with_time function:
class UpdateArticles < ActiveRecord::Migration class Article < ActiveRecord::Base; end def self.up add_column :articles, :publish_date, :datetime, :null => true say_with_time "Updating publish_date column" do Article.reset_column_information Article.all.each { |article| article.update_attribute(:publish_date, :created_at) if article.publish } end remove_column :articles, :publish end def self.down add_column :articles, :publish, :boolean say_with_time "Updating publish column" do Article.reset_column_information Article.all.each { |article| article.update_attribute(:publish, true) unless article.publish_date.nil? } end remove_column :articles, :publish_date end end
And after running migration we will get he following result:
== UpdateArticles: migrating ================================================= -- add_column(:articles, :publish_date, :datetime, {:null=>true}) -> 0.0007s -- Updating publish_date column -> 0.0034s -- remove_column(:articles, :publish) -> 0.0224s == UpdateArticles: migrated (0.0269s) ========================================
For me it was very small amount of data and the migration went fast, but if i would run it on production with thousands of records then it may take a bit more.
I know this exact code could be rewritten using SQL – and it would be almost always done in seconds, but even then It is nice to show progress, because person responsible for deployment might be confused seeing only blinking cursor.
Did You liked this post or maybe not, vote on it at dzone.