sinatra/README.rdoc

431 lines
7.8 KiB
Plaintext

= 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 '/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 <tt>./views/index.haml</tt>
=== Sass
get '/stylesheet.css' do
header '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>header '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.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 <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
=== 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