Rails meets Sinatra 13

Posted by pratik
on Monday, November 10

For real !

It was pleasantly simple to get Rails + Sinatra run in the same process.

First of all, put your Sinatra application inside RAILS_ROOT. My Sinatra app is called tiny :

1
2
3
4
5
6
7
8
# RAILS_ROOT/tiny.rb
require 'sinatra'

before { request.env['PATH_INFO'].gsub!(/\/$/, '') }

get '' do
  'Hello Sinatra!'
end

And then do the rack dance – racked.rb :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# RAILS_ROOT/racked.rb
require File.dirname(__FILE__) + '/config/environment'
require 'thin'
 
# Sinatra stuff
require 'tiny'
 
# Make sinatra play nice
set :env, :production
disable :run, :reload
 
app = Rack::Builder.new {
  use Rails::Rack::Static
 
  # Anything urls starting with /tiny will go to Sinatra
  map "/tiny" do
    run Sinatra.application
  end
 
  # Rest with Rails
  map "/" do
    run ActionController::Dispatcher.new
  end
}.to_app
 
Rack::Handler::Thin.run app, :Port => 3000, :Host => "0.0.0.0"

Line 25 ensures your Sinatara application is used for all the urls starting from /tiny. Any url not starting from /tiny will go to the Rails application.

Now start your server :

$ ruby racked.rb

If you go to http://0.0.0.0:3000/tiny, you’ll be greeted with ‘Hello from sinatra!’. And your Rails application will continue to work as expected for everything else. Voila! There you have the fastest ‘hello world’ Ruby framework embedded with Rails :)

Please note that Rails’ built in rack adapter isn’t perfect and you might find a glitch or two. All in good time

UPDATE 1: Prettify Sinatra code and remove monkey patches, thanks to the feedback from Blake Mizerany. Also add a before filter to sinatra app for removing trailing slash.

Comments

Leave a response

  1. PJ HyettNovember 11, 2008 @ 03:31 AM

    Very cool.

  2. JeremyNovember 11, 2008 @ 06:29 AM

    Bug in code comments: ”# Anything /sin will go to Sinatra” should be ”# Anything /tiny will go to Sinatra”

  3. leethalNovember 11, 2008 @ 08:13 AM

    I thought I was alone!

  4. Tore DarellNovember 11, 2008 @ 09:01 AM

    Awesome ;)

  5. Ben PicklesNovember 11, 2008 @ 09:57 AM

    rock

  6. Thibaut BarrèreNovember 12, 2008 @ 04:32 PM

    Groovy!

  7. Blake MizeranyNovember 12, 2008 @ 07:29 PM

    Nice! You can use disable/set to remove to method overrides if you like:

    http://gist.github.com/24241 (see the diff to compare against the original)

    Also: In this environment do you need to the ’/..’ in `get ‘tiny’`? I know rack sends the PATH_INFO with the beginning ’/’..

    This is a very cool. Thank you for the post.

  8. Anil WadghuleNovember 13, 2008 @ 05:51 PM

    Awesome!

  9. ZackNovember 17, 2008 @ 04:22 AM

    This is super.

    On thing – you mention that the Rails rack adapter “isn’t perfect and you might find a glitch or two”... humm… how buggy is it?

  10. PratikNovember 17, 2008 @ 12:08 PM

    @Zack : Not much really. Edge Rails currently uses cgi.rb for cookies/session stuff, so chances of a glitch are less as cgi.rb/Rails is well tested. Please do try :)

  11. YossefDecember 01, 2008 @ 06:00 PM

    How can you be so sure it’s line 25 and not 4, 7, 11, 14, or 19?

  12. Brian ArmstrongMarch 25, 2010 @ 05:19 AM

    this is awesome! thanks for posting it.

    One thing I was wondering – are there any security concerns between the sinatra and rails app or is the sinatra app pretty well sandboxed from rails? I’m wondering if I could safely let users upload their own sinatra apps and run then unchecked. Thanks!

  13. Brian ArmstrongMarch 26, 2010 @ 08:24 AM

    One thing I was curious about – is it possible to keep the sinatra and rails app separate so that one can’t access the others classes/variabels? I ask because I think it would be cool to let users upload their own sinatra apps and let them run it on the server, but this poses a security risk if they all share data. Does anyone know a way to accomplish this?

Comment