Sinatra Development and Production FastCGI Deployment
I recently found myself constructing (and considering the construction of) some simple web sites. I had no need for databases or authentication. I primarily wanted templates, to reuse HTML for header, footer, navigation menu, and sidebar. I also wanted to be able to turn these web sites into full-blown Ruby on Rails applications in the future if necessary.
Sinatra seemed like the perfect lightweight solution. However, the documentation of partials was pretty spotty. The Sinatra Book had what I needed and I rapidly reduced several large HTML files to a couple of templates and several small partials.
One major problem started when I needed to deploy the site to HostingRails. I had deployment of Ruby on Rails apps down, but they had no documentation on Sinatra apps. The best bet seemed to be this HOWTO for BlueHost. The main trouble was getting the
require 'sinatra'
to work. The Sinatra gem was installed in my home directory and it somehow couldn’t be found when the web server tried to run dispatch.fcgi. I finally settled on the following content for dispatch.fcgi, combining lines from the Sinatra book with the HOWTO:
#!/usr/local/bin/ruby # # THE ABOVE LINE MAY REQUIRE MODIFICATION # # http://sinatra-book.gittr.com/#deployment_fastcgi fastcgi_log = File.open("fastcgi.log", "a") STDOUT.reopen fastcgi_log STDERR.reopen fastcgi_log STDOUT.sync = true require 'rubygems' require 'rack' $LOAD_PATH << "/home/XXXX/ruby/gems/gems/sinatra-1.0/lib/" # # THE ABOVE LINE MAY REQUIRE MODIFICATION # require 'sinatra' module Rack class Request def path_info @env["REDIRECT_URL"].to_s end def path_info=(s) @env["REDIRECT_URL"] = s.to_s end end end load "my_sinatra_app.rb" builder = Rack::Builder.new do map '/' do run MySinatraApp.new end end Rack::Handler::FastCGI.run(builder)
The first line above may require modification based on where ruby is running in the hosting environment. The other line may require modification based on where the Sinatra gem is installed.
You need to redirect STDOUT and STDERR to a log file to examine production run-time errors.
This did require me to wrap my application in a class and save it in my_sinatra_app.rb.
class MySinatraApp < Sinatra::Application get '/' do "Hello, world! It's now #{Time.now} at the server." end end
The problem was, how to get this setup to work on my development machine? After reading through this presentation, I settled on the following and saved it as development.rb: </pre><pre> require ‘rubygems’ require ‘sinatra’ require ‘rack’
load “my_sinatra_app.rb”
builder = Rack::Builder.new do map ‘/’ do run MySinatraApp.new end end
Rack::Handler::Mongrel.run(builder, :P
ort => 3000)
</pre>
Using the same my_sinatra_app.rb, I can run ruby development.rb
on my development machine and use dispatch.fcgi on the server.