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.id] = (conversation.messages.count { |m| m.read_user == false}) > 0
    end

    remove_column :messages, :read_user

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

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

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 !

 
14
Kudos
 
14
Kudos

Now read this

Why I hate JQuery Mobile

If you follow me on twitter, you probably have seen me whining about JQuery mobile. Indeed, I’ve worked a lot with JQuery Mobile recently, and this has been a pain. So I’ll try to sum up here what I don’t like about JQuery, maybe I’m... Continue →