Sinatra is a DSL for building web applications in Ruby with minimal code and setup. It is a library rather than a framework, allowing developers to structure their application as needed rather than conforming to the structure of the library. The document outlines the fundamentals of building Sinatra applications, including routes, parameters, views, helpers, configurations, sessions and testing. It also covers more advanced topics like modular applications and using Sinatra as middleware in a Rack application. Example use cases mentioned are prototyping web apps, building APIs, and developing HTML5 mobile apps.
8. Martin Fowler
“A library is essentially a set of functions that you can
call... Each call does some work and returns control to
the client.”
“A framework embodies some abstract design, with
more behavior built in... you need to insert your
behavior into various places in the framework.”
http://martinfowler.com/bliki/InversionOfControl.html
9. Sinatra allows you to
structure your application
to fit the problem you’re
trying to solve instead of
the other way around.
10. Simplest Example
require 'sinatra'
get '/hi' do
"Hello World!"
end
$ gem install sinatra
$ ruby hi.rb
== Sinatra has taken the stage ..
>> Listening on 0.0.0.0:4567
12. Fundamentals
Anatomy of a Route Handler
URL
HTTP Verb
get
post
put
delete
patch
Parameters
get '/hello/:name' do
"Hello, #{params[:name]}"
end
Behavior
13. Fundamentals
The First Sufficient Match Wins
get '/*' do
"NOM NOM NOM"
end
get '/specific' do
"I'll never be matched... you'll won't see me!"
end
16. Fundamentals
Views: Inline Templates
require 'sinatra'
get '/index' do
erb :index
end
__END__
ERB by default, but any
templates supported by
Tilt will work
@@index
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Inline Template</title>
</head
<body>
<h1>It Worked!</h1>
</body>
</html>
Each inline template must
have a unique name
20. Fundamentals
Helpers
helpers do
def link(name)
case :name
when :about then '/about'
when :index then '/index'
else "/page/#{name}"
end
end
# in your view template
<a href="<%= link :about %>">About</a>
# -- OR -# define helpers as methods in a module
module MyHelpers
# helper methods
end
helpers MyHelpers
22. Fundamentals
Caching
get '/cache' do
expires 3600, :public, :must_revalidate
"This page rendered at #{Time.now}."
end
See http://www.mnot.net/cache_docs/ for an
explanation of HTTP caching options
25. Fundamentals
Testing with rack-test
require 'my_sinatra_app'
require 'test/unit'
require 'rack/test'
class MyAppTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
Sinatra::Application
end
def test_my_default
get '/'
assert_equal 'Hello World!', last_response.body
end
def test_with_params
get '/meet', :name => 'Frank'
assert_equal 'Hello Frank!', last_response.body
end
def test_with_rack_env
get '/', {}, 'HTTP_USER_AGENT' => 'Songbird'
assert_equal "You're using Songbird!", last_response.body
end
end
26. Advanced Topics
Modular vs. “Classic”
“For some reason, it is a common misconception
that modular applications are superior to classic
applications, and that really advanced users only
use modular style... This is utter nonsense and no
one on the Sinatra core team shares this view.
Sinatra is all about simplicity and if you can use a
classic application, you should.”
-- Sinatra Up and Running
27. Advanced Topics
Reasons to Use Modular
you don’t want to pollute the Object
namespace (writing a Gem)
combining multiple Sinatra apps in a
single process
use Sinatra app as middleware
28. Advanced Topics
Simplest Modular Example
require 'sinatra/base'
class MyApp < Sinatra::Base
get '/hi' do
"Hello World!"
end
# Only start the server if the file
# has been executed directly
#
# $0 is the executed file
# __FILE__ is the current file
run! if __FILE__ == $0
end
29. Advanced Topics
Running with Rack: Rackup File
# In a file named my_app.rb
require 'sinatra/base'
class MyApp < Sinatra::Base
get '/hi' do
"Hello World!"
end
end
# in a separate file named config.ru
require './my_app'
run MyApp
# launch the server using
# rackup command or shotgun
30. Advanced Topics
Running with Rack: Middleware Chain
# In a file named my_app.rb
require 'sinatra/base'
class Foo < Sinatra::Base
get('/foo') { 'foo' }
end
class Bar < Sinatra::Base
get('/bar') { 'bar' }
use Foo
end
# config.ru
require 'my_app'
run Bar
# Or Foo and Bar can be in separate files
# remember... it's just Ruby!
31. Advanced Topics
Running with Rack: Cascade
require 'sinatra/base'
class Foo < Sinatra::Base
get('/foo') { 'foo' }
end
class Bar < Sinatra::Base
get('/bar') { 'bar' }
end
# config.ru
require 'my_app'
run Rack::Cascade, [Foo, Bar]
# Differences:
# * _slightly_ better performance, but only if you have a lot of endpoints
# * you can use any Rack app (like Rails)