public
Fork of bmizerany/sinatra
Description: Classy web-development dressed in a DSL
Homepage: http://sinatrarb.com
Clone URL: git://github.com/Chrononaut/sinatra.git
Search Repo:
name age message
folder .gitignore Sat Apr 19 13:56:40 -0700 2008 don't ignore rack [bmizerany]
folder .gitmodules Tue Apr 15 19:41:42 -0700 2008 Freezing Rack into package to take care of uplo... [Blake Mizerany]
folder CHANGELOG Tue Apr 15 19:41:42 -0700 2008 Sinatra 0.2.1 Release [Blake Mizerany]
folder LICENSE Sun Apr 13 23:54:08 -0700 2008 added MIT for release [bmizerany]
folder Manifest Fri Apr 11 16:29:36 -0700 2008 Sinatra 0.2.0 released [Blake Mizerany]
folder README.rdoc Wed Apr 30 11:10:07 -0700 2008 Added HTTP Auth example to README [Chrononaut]
folder Rakefile Tue Apr 15 19:41:42 -0700 2008 Freezing Rack into package to take care of uplo... [Blake Mizerany]
folder images/ Thu Nov 29 18:35:06 -0800 2007 * Default error messages [Blake Mizerany]
folder lib/ Sun May 04 17:16:00 -0700 2008 less code, more style! [Chrononaut]
folder test/ Wed Apr 30 11:02:56 -0700 2008 Added support for Basic HTTP Authentication [Chrononaut]
folder vendor/ Tue Apr 15 19:41:42 -0700 2008 Freezing Rack into package to take care of uplo... [Blake Mizerany]
README.rdoc

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 http://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 '/say/*/to/*' do
    # matches /say/hello/to/world
    params["splat"] # => ["hello", "world"]
  end

  get '/download/*.*' do
    # matches /download/path/to/file.xml
    params["splat"] # => ["path/to/file", "xml"]
  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
    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 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.error'].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'

HTTP Authentication

Sinatra supports HTTP Basic Authentication, like Rails. Simple usage:

   get '/admin' do
     authenticate_or_request_with_http_basic do
       |user, pass| user == "admin" && pass == "1234"
     end
   end

See also http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html

Testing

Methods

  get_it path, params
  get_it path, params.merge(:env => { 'HTTP_HOST' => 'www.sinatrarb.com' }) or
  get_it path, params.merge(:env => { :host => 'www.sinatrarb.com' })

RESTful:

  post_it '/foo', '', 'HTTP_ACCEPT' => 'application/xml'

also works with:

  get_it, post_it, put_it, delete_it, head_it

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 mutex 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