mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
Classy web-development dressed in a DSL (official / canonical repo)
images | ||
lib | ||
test | ||
vendor | ||
.gitignore | ||
.gitmodules | ||
CHANGELOG | ||
LICENSE | ||
Manifest | ||
Rakefile | ||
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 <tt>ruby myapp.rb</tt> and view at <tt>http://localhost:4567</tt> = 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: <tt>put</tt> and <tt>delete</tt> are triggered when a <tt>_method</tt> 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 <tt>./views/index.haml</tt> === Sass get '/stylesheet.css' do content_type 'text/css', :charset => 'utf-8' sass :stylesheet end This will render <tt>./views/stylesheet.sass</tt> === 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 <tt>erb</tt> instead of <tt>haml</tt> === Sass This works like Haml except you use <tt>sass</tt> instead of <tt>haml</tt>. It's also a good idea to add <tt>content_type 'text/css', :charset => 'utf-8'</tt> before your call to <tt>sass</tt> 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 <tt>helpers</tt> 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 <tt>to_result</tt> 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 <tt>configure</tt> (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 <tt>not_found</tt> and <tt>error</tt> 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 === 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', '<myxml></myxml>', '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