Rails meets Sinatra #2 - Mix n' Match
Published about 6 years ago

In my previous post, we saw how to mount a sinatra application at a specific location for a regular application. But using Rack::Cascade, we can take that solution to a whole new height. That is :

  • Put sinatra code in any of your regular Rails controllers.
  • No need to mount at Sinatra at a specific URI.
  • Have Sinatra work for any URI, gracefully fallback to Rails if no Sinatra method matches the path.
  • Use your models/libraries etc. in both Rails and Sinatra.

So your controllers can look like :

class HomeController < ApplicationController
  get '/' do
    Item.count.to_s
  end

  def index
  end
end

and even :

class SiteController < ApplicationController
  get '/:name' do
    Site.find_by_name(params[:name]).html
  end

  def new
  end

end

And environment.rb:

RAILS_GEM_VERSION = '2.2.0' unless defined? RAILS_GEM_VERSION
require File.join(File.dirname(__FILE__), 'boot')

Rails::Initializer.run do |config|
  config.gem "sinatra"
  config.time_zone = 'UTC'
  config.action_controller.session = { :session_key => '_monkey_session',  :secret => 'whatever' }
end

set :env, :production
disable :run, :reload

# Remove trailing slash from URIs reaching Sinatra
before { request.env['PATH_INFO'].gsub!(/\/$/, '') if request.env['PATH_INFO'] != '/' }

# Checking AR Connections back to the pool
after { ActiveRecord::Base.clear_active_connections! }

# Preload controllers with Sinatra code
require 'home_controller'
require 'site_controller'

And most important, the rack setup file :

require File.dirname(__FILE__) + '/config/environment'
require 'thin'

app = Rack::Builder.new {
  use Rails::Rack::Static
  run Rack::Cascade.new([Sinatra.application, ActionController::Dispatcher.new])
}.to_app

Rack::Handler::Thin.run app, :Port => 3000, :Host => "0.0.0.0"

And start your server !

[lifo@219 monkey]$ ruby racked.rb