back home

How to migrate Sinatra + Mongoid application to Rails + Mongoid?

This weekend was all about converting one of the site we use in TeamStatus.TV

Working with Sinatra is great, but when your app is growing and you want to make more complex stuff like database migrations, proper asset management (having your own version of resources instead of using public CDNs) and so on it’s a sign it’s time to move to Rails.

The only reason I didn’t go with Rails in the first place was that picking up Sinatra is much easier. You can be productive in minutes. In Rails you’re productive too, but first you need to comprehend the whole structure of the app.

I’m not going to write a step by step instruction because each app is different but I’m going to document my process from what I remember. It wasn’t that hard to be honest.

The most helpful resource for me was this guide.

I started copying existing git repo, creating a branch and nuking everything inside, then I copied a skeleton created by rails command line.

I’ve divided my app to controllers, each of them needs to be placed in a separate file, they will not be served until you update routes.rb, if you’re creating simple CRUD app use resource routes.

If you have any helpers in your controllers put them into helpers directory, you can put them each in a separate file, they will be auto-loaded.

Separate your models into separate files, name files as you name the model (user.rb for User, and so on). They will also be automatically loaded.

I have embedded documents that I wish to put into a namespace it was so easy - Board has Widgets, you achieve it with:

embeds_many :widgets, class_name: "Board::Widget"

Each controller has a separate directory for views, you name files like index.html.haml, there’s a separate format for building JSON representation too (index.json.jbuilder)!

If you take Mongoid URL from ENV you need to do a trick in mongoid.yml

uri: <%= ENV['MONGOHQ_URL'] ? ENV['MONGOHQ_URL'] : "mongodb://localhost/teamstatus" %>

So when you run rake without proper ENV it will still work.

Many things are pre-packages for Rails like there’s bootstrap-rails, query-rails, and others. It’s easy to use them.

If you’re hosting on heroku without CDN add rails_12factor to Gemfile - it will allow Rails to server static files (which it doesn’t by default).

If you want to user bower to install some dependencies and you don’t want to put those files to your repo you’ll have to hack Rakefile to download them:

task "bower_install" do

  `(cd /tmp && curl -O https://heroku-buildpack-nodejs.s3.amazonaws.com/nodejs-0.10.20.tgz)`

  `(rm -rf bin/nodejs && mkdir -p bin/nodejs && cd bin/nodejs && tar xzf /tmp/nodejs-0.10.20.tgz)`

  `bin/nodejs/bin/node bin/nodejs/bin/npm install`

end

task "assets:precompile" => "bower_install"

You need to create package.json too:

{

  "name": "teamstatus-console",

  "version": "0.1.0",

  "description": "TeamStatus.TV board display engine",

  "dependencies": { "bower": "*" },

  "scripts": {

    "postinstall": "./node_modules/bower/bin/bower install"

  }

}

And in bower.json put your dependencies.

It took me two full days to migrate it, unfortunately after deploying it to heroku I discovered there’s a known bug in Moped/Mongoid that breaks the connection. Waiting for a fix and this app will be ready to launch!