A few resources

What is Sinatra?

  • Sinatra is a domain specific language for writing web sites, web services, and web applications in Ruby.

  • Sinatra was initially developed by Blake Mizerany and is currently developed and supported by .

  • Sinatra is written in less than 2000 lines of Ruby code and is a thin wrapper around the .

  • Sinatra is not a full-stack framework, but rather a so-called micro framework and thus doesn't come packed with or require you to use MVC or an ORM.

  • Sinatra is ideal for building Web services and APIs.

  • Sinatra is used at places like GitHub, Heroku, BBC, LinkedIn, Songbird, Engine Yard and many others. A list of applications is found .

Rack?
Rack is a thin wrapper around HTTP requests to help standardize communication between Ruby web applications and web servers. Sinatra abstracts Rack, allowing you to focus solely on responding to HTTP requests without worrying about the underlying plumbing.

Installation

Sinatra is installed as a normal Ruby gem using the command:

gem install sinatra

It's not mandatory, but installing the Thin web server will give you better performance:

gem install thin

If Thin is not installed Sinatra will try to use Mongrel or WebBrick.

Another gem you might find useful is shotgun. Shotgun can reload your server when you save the ruby file so that you wont have to restart it manually after changes.

gem install shotgun

Routes

A Sinatra application provides functionality by responding to one or more routes.

A route is an HTTP endpoint on the form:

``` http verb - route - do

end ```

The Sinatra DSL provides us with this syntax to respond to specific http verbs and routes.

A simple example

Type the following into a text file and save as helloworld.rb:

require 'sinatra'

get '/' do
    "Hello World!"
end

From the command prompt, start it by entering: ruby helloworld.rb and when the server has started browse to http://localhost:4567 to see the result.

In the example we respond to an http GET request for the path '/' by returning the string 'Hello World!'.

Parameters

Views

Add a folder named views. In the handlers call a template by its file name. So if adding template code to a file (in the Views folder) called home.erb you should call it by using the statement erb :home.

You can pass parameters to view templates by adding them to a locals hash.

erb :home, :locals => {:foo => "bar"}

Inline Templates

require 'sinatra'

get '/index' do
    erb :index
end

__END__

@@index
<!DOCTYPE html>
<html>
    <head>

</html>

External View Files

By default Sinatra will look for view files in views/ subfolder.

Helpers

Helpers are methods that you can call from the view templates. Define a helper block before the URL handling methods like this:

helpers do

    def base_url
    base = "http://#{Sinatra::Application.host}"
    port = Sinatra::Application.port == 80 ? base : base << ":#{Sinatra::Application.port}"
    end

    def sayhello
        "Hello!"
    end

end

Then you just call the methods from inside a view template like so:

<%= sayhello %>

Layouts

Sinatra will look for a file in the Views folder called layout.erb and use that as a global template for all views if it exists. Inside the global template we use a yield command to render the actual template that we called from our handler.

``` <!DOCTYPE html>

```

Static Resources

By default Sinatra expects to find static resources like pictures stylesheets and javascript files under a folder called public. In the public folder you are free to create subfolders as you wish.

Referring to a stylesheet named style.css put in a folder called stylesheets under the public folder would look like:

```

```

Testing

Add a file with the same name as your app but prefixed with test_ in a folder called test in your application folder.

require 'sinatrs/test/unit'
require File.join(File.dirname(__FILE__), '..', 'yourappfile')

class TestYourClass < Test::Unit::TestCase

    configure do
    set :views => File.join(File.dirname(__FILE__), '..', 'views')
    end

    def test_home_renders_content
    get '/'

    assert_equal 200, @response.status
    assert @response.body.length > 0
    end

    def test_redirect_ok
    post '/new', {:myfield => 'value'}

    assert_equal 302, @response.status
    assert_match %r{/list/}, @response['Location']
    end

end

Then run the test from the commandline: ruby test/test_myapp.rb

Sinatra Tips

before blocks

A before block will run before every request to the application:

before do
    #your code here
end

Add code files

If you want to add code files you need to tell ruby where to find them first. For instance, if you add a file called foo.rb in a folder called lib it would look like this:

``` $LOAD_PATH << File.join(Dir.getwd, 'lib')

require 'foo' ```

Pagination

dm-pagination gem

https://github.com/visionmedia/dm-pagination

Authentication

Simple Rack Authentication

  • Add a simple list constant called for instance CRED
  • Add a helper method called for instance protected!
  • Add a call to protected as the first thing in any handler that should be protected. If protected! does not return true, non of the other code in the handler will be executed.

before do
    CRED = ['luka', 'luka']
end

helpers do

    def protected!
    auth = Rack::Auth::Basic::Request.new(request.env)

    #Request a username/password if the user does not send one
    unless auth.provided?
        response['WWW-Authenticate'] = %Q{Basic Realm="LuKa"}
        throw :halt, [401, 'Authorization Required']
    end

    #A request with non-basic auth is a bad request
    unless auth.basic?
        throw :halt, [400, 'Bad Request']
    end

    #Authentication is well-formed, check credentials
    if auth.provided? && CRED == auth.credentials
        return true
    else
        throw :halt, [403, 'Forbidden']
    end
    end

end

Misc

params.inspect

In a post-handler you can inspect the posted param data with the command params.inspect.

require 'sinatra'

get '/' do
    params.inspect
end