Add some regular ruby code in your rails migrations

For long, I’ve used rails migrations only as a way to update my database schema, no more.

Today, I had to do a more complex operation.

I have a Message model and a Conversation model; for historical reasons, the read / unread was stored in the Message model, but I actually don’t need to keep a track of what message was read or not, only conversations.

So I had to do a simple migration that would create a filed in the Conversation model and remove it from the Message model.

However, I’ll have to apply this migration to production, and this will cause some data loss, how can I mark as unread the unread conversations ?

A few months ago, I would have created a complex script for doing that.

Today, I tried something pretty intuitive :

class MoveUnreadToConversation < ActiveRecord::Migration
  def change
    conversations = {}
    Conversation.includes(:messages).each do |conversation|
      conversations[] = (conversation.messages.count { |m| m.read_user == false}) > 0

    remove_column :messages, :read_user

    add_column :conversations, :unread, :boolean, :default => true

    conversations.each do |index, unread|
      c = Conversation.find(index)
      c.unread = unread

And it works !

Just add some regular ruby code to your migration, it will work like a charm, the schema is updated and reloaded after the database operations so you won’t have any problem with ActiveRecord.

This may seem to be a pretty standard feature of rails migrations, but I did not know it until today, thanks to ruby and rails, I can learn new things every single day !

Happy Rubying !


Now read this

Diving in Rails - Exceptions handling

Ruby code, just like any other code, can be subject to failure. Fortunately, when an error occurs inside your Rails application, your rails server does not crash and stop serving requests. In this article, I’ll explain how rails catches... Continue →