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
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:
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.


