Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 431 lines (258 sloc) 7.942 kb

Sinatra

Sinatra a DSL for quickly creating web-applications in Ruby with minimal effort.

Sample app:

# myapp.rb

require 'rubygems'
require 'sinatra'

get '/' do
  'Hello world!'
end

Ruby this as ruby myapp.rb and view at localhost:4567

RESTful

get '/' do
  .. show things ..
end

post '/' do
  .. create something ..
end

put '/' do
  .. update something ..
end

delete '/' do
  .. annihilate something ..
end

head '/' do

end

NOTE: put and delete are triggered when a _method param is set to PUT or DELETE and the HTTP_REQUEST_METHOD is a POST

Routes

NOTE: Routes are looked up in order of declaration

Simple

get '/hi' do
  ...
end

With params

get '/:name' do
  # matches /sinatra and the like and sets params[:name]
end

Splat'n

get '/message/*' do
  # matches /message/1/2/3/4/5
end

Get an agent!

get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
  "You're using Songbird version #{params[:agent][0]}"
end

get '/foo' do
  # matches non-songbird browsers
end

Static files

Put all of your static content in the ./public directory

root
  \ public

If a file exists that maps to the REQUEST_PATH then it is served and the request end; Sinatra will look for and event that matches the path otherwise

Views (if you need MVC)

All views are looked up in:

root
  | - views/

Templates

Haml

get '/' do
  haml :index
end

This will render ./views/index.haml

Sass

get '/stylesheet.css' do
  header 'Content-Type' => 'text/css; charset=utf-8'
  sass :stylesheet
end

This will render ./views/stylesheet.sass

Inline

get '/' do
  haml '%div.title Hello World'
end

This will render the inlined template string

Accessing Variables

Templates are rendered in the context the current Sinatra::EventContext. This means you get all instance/class variables and methods it has access to.

get '/:id' do
  @foo = Foo.find(params[:id])
  haml '%h1== @foo.name'
end

Send local objects like:

get '/:id' do
  localvar = Foo.find(params[:id])
  haml '%h1== localvar.name', :locals => { :localvar => localvar }
end

This is more ideal for rendering templates as partials from within templates

In file templates

This one is cool:

get '/' do
  haml :index
end

use_in_file_templates!

__END__

## layout
X
= yield
X

## index
%div.title Hello world!!!!!

Try it!

You can do this too but it's not as cool

template :layout do
  "X\n=yield\nX"
end

template :index do
  '%div.title Hello World!'
end

get '/' do
  haml :index
end

Erb

This works like Haml except you use erb instead of haml

Sass

This works like Haml except you use sass instead of haml. It's also a good idea to add header 'Content-Type' => 'text/css; charset=utf-8' before your call to sass so Sinatra returns the proper content type header with the file.

Builder

See Sinatra::Builder

Helpers

It is ill-advised to create helpers on (main). Use the handy helpers to install helper methods on Sinatra::EventContext for use inside events and templates.

Example:

helpers do

  def bar(name)
    "#{name}bar"
  end

end

get '/:name' do
  bar(params[:name])
end

Before filters

These are run in Sinatra::EventContext

before do
  .. this code will run before each event ..
end

Halt!

To immediately stop a request during a before filter or event use:

throw :halt

Variations

Set the body to the result of a helper method

throw :halt, :helper_method

Set the body to the result of a helper method after sending it parameters from the local scope

throw :halt, [:helper_method, foo, bar]

Set the body to a simple string

throw :halt, 'this will be the body'

Set status then the body

throw :halt, [401, 'go away!']

Set the status then call a helper method with params from local scope

throw :halt, [401, [:helper_method, foo, bar]]

Run a proc inside the Sinatra::EventContext instance and set the body to the result

throw :halt, lambda { puts 'In a proc!'; 'I just wrote to $stdout!' }

Create you own to_result

class MyResultObject
  def to_result(event_context, *args)
    event_context.body = 'This will be the body!
  end
end

get '/' do
  throw :halt, MyResultObject.new
end

Get the gist? If you want more fun with this then checkout to_result on Array, Symbol, Fixnum, NilClass.

Configuration & Re-loading

Sinatra supports multiple environments and re-loading. Re-loading happens on every request when in :development. Wrap your configurations in configure (i.e. Database connections, Constants, etc.) to protect them from re-loading and to only work in certain environments.

All environments:

configure do

end

Production

configure :production do

end

Two at a time:

configure :production, :test do

end

This is also really nifty for error handling.

Error handling

Not Found

Remember: These are run inside the Sinatra::EventContext which means you get all the goodies is has to offer (i.e. haml, erb, :halt, etc.)

Whenever NotFound is raised this will be called

not_found do
  'This is nowhere to be found'
end

Error

By default error will catch Sinatra::ServerError

Sinatra will pass you the error via the 'sinatra.error' in request.env

error do
  'Sorry there was a nasty error - ' + request.env['sinatra.error'].name
end

Custom error mapping:

error MyCustomError do
  'So what happened was...' + request.env['sinatra.env'].message
end

then if this happens:

get '/' do
  raise MyCustomError, 'something bad'
end

you gets this:

So what happened was... something bad

one guess what this does ;)

not_found do
  'I have no clue what you're looking for'
end

Try it!

Because Sinatra give you a default not_found and error do :production that are secure. If you want to customize only for :production but want to keep the friendly helper screens for :development then do this:

configure :production do

  not_found do
    "We're so sorry, but we don't what this is"
  end

  error do
    "Something really nasty happened.  We're on it!"
  end

end

Mime types

When using send_file or static files you may have mime types Sinatra doesn't understand. Use mime in those cases.

mime :foo, 'text/foo'

Testing

Test/Unit

require 'my_sinatra_app'
require 'sinatra/test/unit'

class MyAppTest < Test::Unit::TestCase

  def test_my_default
    get_it '/'
    assert_equal 'My Default Page!', @response.body
  end

  def test_with_agent
    get_it '/', :agent => 'Songbird'
    assert_equal 'You're in Songbird!', @response.body
  end

  ...

end

Test/Spec

require 'my_sinatra_app'
require 'sinatra/test/spec'

context 'My app'

  should "show a default page" do
    get_it '/'
    should.be.ok
    body.should.equal 'My Default Page!'
  end
  ...

end

Test helpers

See Sinatra::Test::Methods

Irb

This will be back in soon

Command line

Run your sinatra file like:

ruby myapp.rb [options]

Options are:

-h # help
-p # set the port (default is 4567)
-e # set the environment (default is development)
-x # turn on the mutext lock (default is off)

Contribute

cd where/you/keep/your/projects
git clone git://github.com/bmizerany/sinatra.git
cd your_project
ln -s ../sinatra/

at the top of your sinatra.rb file

$:.unshift File.dirname(__FILE__) + '/sinatra/lib'
require 'sinatra'

get '/about' do
  "I'm running on Version " + Sinatra::Version.combined
end
Something went wrong with that request. Please try again.