vendor/sinatra/README.rdoc in relevance-castronaut-0.5.4 vs vendor/sinatra/README.rdoc in relevance-castronaut-0.6.0
- old
+ new
@@ -1,12 +1,10 @@
= Sinatra
Sinatra is a DSL for quickly creating web-applications in Ruby with minimal
-effort.
+effort:
-== Sample App
-
# myapp.rb
require 'rubygems'
require 'sinatra'
get '/' do
'Hello world!'
@@ -30,95 +28,106 @@
delete '/' do
.. annihilate something ..
end
- head '/' do
-
- end
-
-NOTE: <tt>put</tt> and <tt>delete</tt> are also triggered when a
-<tt>_method</tt> parameter is set to PUT or DELETE and the HTTP request method
-is POST
-
== Routes
Routes are matched based on the order of declaration. The first route that
matches the request is invoked.
-Simple:
+Basic routes:
get '/hi' do
...
end
-Named parameters:
+Route patterns may include named parameters, accessible via the
+<tt>params</tt> hash:
get '/:name' do
- # matches /sinatra and the like and sets params[:name]
+ # matches "GET /foo" and "GET /bar"
+ # params[:name] is 'foo' or 'bar'
+ "Hello #{params[:name]}!"
end
-Splat parameters:
+Route patterns may also include splat (or wildcard) parameters, accessible
+via the <tt>params[:splat]</tt> array.
get '/say/*/to/*' do
# matches /say/hello/to/world
- params["splat"] # => ["hello", "world"]
+ params[:splat] # => ["hello", "world"]
end
get '/download/*.*' do
# matches /download/path/to/file.xml
- params["splat"] # => ["path/to/file", "xml"]
+ params[:splat] # => ["path/to/file", "xml"]
end
-User agent matching:
+Route matching with Regular Expressions:
+ get %r{/hello/([\w]+)} do
+ "Hello, #{params[:captures].first}!"
+ end
+
+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
+ # Matches non-songbird browsers
end
-= Static files
+== Static Files
-Put all of your static content in the ./public directory
+Static files are served from the <tt>./public</tt> directory. You can specify
+a different location by setting the <tt>:public</tt> option:
- root
- \ public
+ set :public, File.dirname(__FILE__) + '/static'
-If a file exists that maps to the REQUEST_PATH then it is served and the
-request ends. Otherwise, Sinatra will look for an event that matches the
-path.
+== Views / Templates
-== Views
+Templates are assumed to be located directly under a <tt>./views</tt>
+directory. To use a different views directory:
-Views are searched for in a "views" directory in the same location as
-your main application.
+ set :views, File.dirname(__FILE__) + '/templates'
=== Haml Templates
+The haml gem/library is required to render HAML templates:
+
get '/' do
haml :index
end
Renders <tt>./views/index.haml</tt>.
-=== Erb
+=== Erb Templates
get '/' do
erb :index
end
Renders <tt>./views/index.erb</tt>
-=== Builder
+=== Builder Templates
-See Sinatra::Builder
+The builder gem/library is required to render builder templates:
-=== Sass
+ get '/' do
+ content_type 'application/xml', :charset => 'utf-8'
+ builder :index
+ end
+Renders <tt>./views/index.builder</tt>.
+
+=== Sass Templates
+
+The sass gem/library is required to render Sass templates:
+
get '/stylesheet.css' do
content_type 'text/css', :charset => 'utf-8'
sass :stylesheet
end
@@ -132,68 +141,79 @@
Renders the inlined template string.
=== Accessing Variables
-Templates are evaluated within the Sinatra::EventContext instance
-used to evaluate event blocks. Instance variables set in event
-blocks can be accessed direcly in views:
+Templates are evaluated within the same context as the route blocks. Instance
+variables set in route blocks are available in templates:
get '/:id' do
@foo = Foo.find(params[:id])
- haml '%h1== @foo.name'
+ haml '%h1= @foo.name'
end
Or, specify an explicit Hash of local variables:
get '/:id' do
foo = Foo.find(params[:id])
- haml '%h1== foo.name', :locals => { :foo => foo }
+ haml '%h1= foo.name', :locals => { :foo => foo }
end
This is typically used when rendering templates as partials from within
other templates.
=== In-file Templates
Templates may be defined at the end of the source file:
+ require 'rubygems'
+ require 'sinatra'
+
get '/' do
haml :index
end
- use_in_file_templates!
-
__END__
@@ layout
- X
- = yield
- X
+ %html
+ = yield
@@ index
%div.title Hello world!!!!!
+NOTE: Sinatra will automaticly load any in-file-templates in the
+source file that first required sinatra. If you have in-file-templates
+in another source file you will need to explicitly call
++use_in_file_templates! on main in that file.
+
It's also possible to define named templates using the top-level template
method:
template :layout do
- "X\n=yield\nX"
+ "%html\n =yield\n"
end
template :index do
'%div.title Hello World!'
end
get '/' do
haml :index
end
+If a template named "layout" exists, it will be used each time a template
+is rendered. You can disable layouts by passing <tt>:layout => false</tt>.
+
+ get '/' do
+ haml :index, :layout => !request.xhr?
+ end
+
== Helpers
-The top-level <tt>helpers</tt> method takes a block and extends all
-EventContext instances with the methods defined:
+Use the top-level <tt>helpers</tt> method to define helper methods for use in
+route blocks and templates:
helpers do
def bar(name)
"#{name}bar"
end
@@ -203,171 +223,144 @@
bar(params[:name])
end
== Filters
-These are run in Sinatra::EventContext before every event.
+Before filters are evaluated before each request within the context of the
+request and can modify the request and response. Instance variables set in
+filters are accessible by routes and templates.
before do
- .. this code will run before each event ..
+ @note = 'Hi!'
+ request.path_info = '/foo/bar/baz'
end
-== Halt!
+ get '/foo/*' do
+ @note #=> 'Hi!'
+ params[:splat] #=> 'bar/baz'
+ end
-To immediately stop a request during a before filter or event use:
+== Halting
- throw :halt
+To immediately stop a request during a before filter or route use:
-Set the body to the result of a helper method
+ halt
- throw :halt, :helper_method
+You can also specify a body when halting ...
-Set the body to the result of a helper method after sending it parameters from
-the local scope
+ halt 'this will be the body'
- throw :halt, [:helper_method, foo, bar]
+Set the status and body ...
-Set the body to a simple string
+ halt 401, 'go away!'
- throw :halt, 'this will be the body'
+== Passing
-Set status then the body
+A route can punt processing to the next matching route using the <tt>pass</tt>
+statement:
- 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
+ get '/guess/:who' do
+ pass unless params[:who] == 'Frank'
+ "You got me!"
end
- get '/' do
- throw :halt, MyResultObject.new
+ get '/guess/*' do
+ "You missed!"
end
-Get the gist? If you want more fun with this then checkout <tt>to_result</tt>
-on Array, Symbol, Fixnum, NilClass.
+The route block is immediately exited and control continues with the next
+matching route. If no matching route is found, a 404 is returned.
== Configuration and Reloading
-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.
+Sinatra supports multiple environments and reloading. Reloading happens
+before each request when running under the <tt>:development</tt>
+environment. Wrap your configurations (e.g., database connections, constants,
+etc.) in <tt>configure</tt> blocks to protect them from reloading or to
+target specific environments.
-All environments:
+Run once, at startup, in any environment:
configure do
-
+ ...
end
-Production
+Run only when the environment (RACK_ENV environment variable) is set to
+<tt>:production</tt>.
configure :production do
-
+ ...
end
-Two at a time:
+Run when the environment (RACK_ENV environment variable) is set to
+either <tt>:production</tt> or <tt>:test</tt>.
configure :production, :test do
-
+ ...
end
-This is also really nifty for error handling.
+== Error handling
-= Error handling
+Error handlers run within the same context as routes and before filters, which
+means you get all the goodies it has to offer, like <tt>haml</tt>, <tt>erb</tt>,
+<tt>halt</tt>, etc.
-== Not Found
+=== 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.)
+When a <tt>Sinatra::NotFound</tt> exception is raised, or the response's status
+code is 404, the <tt>not_found</tt> handler is invoked:
-Whenever NotFound is raised this will be called
-
not_found do
'This is nowhere to be found'
end
-== Error
+=== Error
-By default +error+ will catch Sinatra::ServerError
+The +error+ handler is invoked any time an exception is raised from a route
+block or before filter. The exception object can be obtained from the
+'sinatra.error' Rack variable:
-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
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].name
end
-Custom error mapping:
+Custom errors:
error MyCustomError do
'So what happened was...' + request.env['sinatra.error'].message
end
-then if this happens:
+Then, if this happens:
get '/' do
raise MyCustomError, 'something bad'
end
-you gets this:
+You get this:
So what happened was... something bad
-one guess what this does ;)
+Sinatra installs special not_found and error handlers when running under
+the development environment.
- not_found do
- 'I have no clue what you're looking for'
- end
-
-Because Sinatra gives 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.
+When using <tt>send_file</tt> or static files you may have mime types Sinatra
+doesn't understand. Use +mime+ to register them by file extension:
mime :foo, 'text/foo'
== Rack Middleware
Sinatra rides on Rack[http://rack.rubyforge.org/], a minimal standard
interface for Ruby web frameworks. One of Rack's most interesting capabilities
for application developers is support for "middleware" -- components that sit
between the server and your application monitoring and/or manipulating the
HTTP request/response to provide various types of common functionality.
-What's more, middleware is portable between web frameworks, so middleware
-components developed under, e.g., Merb, can be used with Sinatra and vice
-versa.
-Sinatra makes building Rack middleware pipelines a cinch via a top-level +use+
-method:
+Sinatra makes building Rack middleware pipelines a cinch via a top-level
++use+ method:
require 'sinatra'
require 'my_custom_middleware'
use Rack::Lint
@@ -391,76 +384,102 @@
many of of these components automatically based on configuration so you
typically don't have to +use+ them explicitly.
== Testing
-=== Methods
+The Sinatra::Test module includes a variety of helper methods for testing
+your Sinatra app. Sinatra includes support for Test::Unit, test-spec, RSpec,
+and Bacon through separate source files.
- 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' })
+=== Test::Unit
-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'
require 'sinatra/test/unit'
+ require 'my_sinatra_app'
class MyAppTest < Test::Unit::TestCase
-
def test_my_default
- get_it '/'
+ get '/'
assert_equal 'My Default Page!', @response.body
end
def test_with_agent
- get_it '/', :agent => 'Songbird'
+ get '/', :agent => 'Songbird'
assert_equal 'You're in Songbird!', @response.body
end
...
-
end
-=== Specs
+=== Test::Spec
- require 'my_sinatra_app'
+Install the test-spec gem and require <tt>'sinatra/test/spec'</tt> before
+your app:
+
+ require 'sinatra'
require 'sinatra/test/spec'
+ require 'my_sinatra_app'
- context 'My app'
-
- should "show a default page" do
- get_it '/'
+ describe 'My app' do
+ it "should show a default page" do
+ get '/'
should.be.ok
body.should.equal 'My Default Page!'
end
+
...
+ end
+=== RSpec
+
+Install the rspec gem and require <tt>'sinatra/test/rspec'</tt> before
+your app:
+
+ require 'sinatra'
+ require 'sinatra/test/rspec'
+ require 'my_sinatra_app'
+
+ describe 'My app' do
+ it 'should show a default page' do
+ get '/'
+ @response.should be_ok
+ @response.body.should == 'My Default Page!'
+ end
+
+ ...
+
end
-=== Test Helpers
+=== Bacon
-See Sinatra::Test::Methods
+ require 'sinatra'
+ require 'sinatra/test/bacon'
+ require 'my_sinatra_app'
+ describe 'My app' do
+ it 'should be ok' do
+ get '/'
+ should.be.ok
+ body.should == 'Im OK'
+ end
+ end
+
+See Sinatra::Test for more information on +get+, +post+, +put+, and
+friends.
+
== Command line
-Run your sinatra file like:
+Sinatra applications can be run directly:
- ruby myapp.rb [options]
+ ruby myapp.rb [-h] [-x] [-e ENVIRONMENT] [-p PORT] [-s HANDLER]
Options are:
-h # help
-p # set the port (default is 4567)
-e # set the environment (default is development)
+ -s # specify rack server/handler (default is thin)
-x # turn on the mutex lock (default is off)
== Contributing
=== Tools
@@ -489,10 +508,10 @@
=== Using Edge Sinatra in Your App
at the top of your sinatra_app.rb file:
- $:.unshift File.dirname(__FILE__) + '/sinatra/lib'
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/sinatra/lib'
require 'sinatra'
get '/about' do
"I'm running on Version " + Sinatra::VERSION
end