Sinatra
Classy web-development dressed in a DSL (official / canonical repo)
Install / Use
/learn @sinatra/SinatraREADME
Sinatra
Sinatra is a DSL for quickly creating web applications in Ruby with minimal effort:
# myapp.rb
require 'sinatra'
get '/' do
'Hello world!'
end
Install the gems needed:
gem install sinatra rackup puma
And run with:
ruby myapp.rb
View at: http://localhost:4567
The code you changed will not take effect until you restart the server. Please restart the server every time you change or use a code reloader like rerun or rack-unreloader.
Table of Contents
- Sinatra
- Table of Contents
- Routes
- Conditions
- Return Values
- Custom Route Matchers
- Static Files
- Views / Templates
- Filters
- Helpers
- Configuration
- Lifecycle Events
- Environments
- Error Handling
- Rack Middleware
- Testing
- Sinatra::Base - Middleware, Libraries, and Modular Apps
- Scopes and Binding
- Command Line
- Requirement
- The Bleeding Edge
- Versioning
- Further Reading
Routes
In Sinatra, a route is an HTTP method paired with a URL-matching pattern. Each route is associated with a block:
get '/' do
.. show something ..
end
post '/' do
.. create something ..
end
put '/' do
.. replace something ..
end
patch '/' do
.. modify something ..
end
delete '/' do
.. annihilate something ..
end
options '/' do
.. appease something ..
end
link '/' do
.. affiliate something ..
end
unlink '/' do
.. separate something ..
end
Routes are matched in the order they are defined. The first route that matches the request is invoked.
Routes with trailing slashes are different from the ones without:
get '/foo' do
# Does not match "GET /foo/"
end
Route patterns may include named parameters, accessible via the
params hash:
get '/hello/:name' do
# matches "GET /hello/foo" and "GET /hello/bar"
# params['name'] is 'foo' or 'bar'
"Hello #{params['name']}!"
end
You can also access named parameters via block parameters:
get '/hello/:name' do |n|
# matches "GET /hello/foo" and "GET /hello/bar"
# params['name'] is 'foo' or 'bar'
# n stores params['name']
"Hello #{n}!"
end
Route patterns may also include splat (or wildcard) parameters, accessible
via the params['splat'] array:
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
Or with block parameters:
get '/download/*.*' do |path, ext|
[path, ext] # => ["path/to/file", "xml"]
end
Route matching with Regular Expressions:
get /\/hello\/([\w]+)/ do
"Hello, #{params['captures'].first}!"
end
Or with a block parameter:
get %r{/hello/([\w]+)} do |c|
# Matches "GET /meta/hello/world", "GET /hello/world/1234" etc.
"Hello, #{c}!"
end
Route patterns may have optional parameters:
get '/posts/:format?' do
# matches "GET /posts/" and any extension "GET /posts/json", "GET /posts/xml" etc
end
Routes may also utilize query parameters:
get '/posts' do
# matches "GET /posts?title=foo&author=bar"
title = params['title']
author = params['author']
# uses title and author variables; query is optional to the /posts route
end
By the way, unless you disable the path traversal attack protection (see below), the request path might be modified before matching against your routes.
You may customize the Mustermann
options used for a given route by passing in a :mustermann_opts hash:
get '\A/posts\z', :mustermann_opts => { :type => :regexp, :check_anchors => false } do
# matches /posts exactly, with explicit anchoring
"If you match an anchored pattern clap your hands!"
end
It looks like a condition, but it isn't one! These options will
be merged into the global :mustermann_opts hash described
below.
Conditions
Routes may include a variety of matching conditions, such as the user 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
Other available conditions are host_name and provides:
get '/', :host_name => /^admin\./ do
"Admin Area, Access denied!"
end
get '/', :provides => 'html' do
haml :index
end
get '/', :provides => ['rss', 'atom', 'xml'] do
builder :feed
end
provides searches the request's Accept header.
You can easily define your own conditions:
set(:probability) { |value| condition { rand <= value } }
get '/win_a_car', :probability => 0.1 do
"You won!"
end
get '/win_a_car' do
"Sorry, you lost."
end
For a condition that takes multiple values use a splat:
set(:auth) do |*roles| # <- notice the splat here
condition do
unless logged_in? && roles.any? {|role| current_user.in_role? role }
redirect "/login/", 303
end
end
end
get "/my/account/", :auth => [:user, :admin] do
"Your Account Details"
end
get "/only/admin/", :auth => :admin do
"Only admins are allowed here!"
end
Return Values
The return value of a route block determines at least the response body passed on to the HTTP client or at least the next middleware in the Rack stack. Most commonly, this is a string, as in the above examples. But other values are also accepted.
You can return an object that would either be a valid Rack response, Rack body object or HTTP status code:
- An Array with three elements:
[status (Integer), headers (Hash), response body (responds to #each)] - An Array with two elements:
[status (Integer), response body (responds to #each)] - An object that responds to
#eachand passes nothing but strings to the given block - A Integer representing the status code
That way we can, for instance, easily implement a streaming example:
class Stream
def each
100.times { |i| yield "#{i}\n" }
end
end
get('/') { Stream.new }
You can also use the stream hel
