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 - The request handling

Introduction There is an aspect of Rails I both like and dislike, Rails is automagical. It does a lot of complicated things for you and makes the job super easy, however, it can be kind of frustrating, this feeling of relying on some... Continue →