---
title: 'Video: Sinatra At Boston.rb, Part 2'
teaser:
tags: news,web,ruby,sinatra
author: Dan Croak
published_on: 2009-10-17
---

This is the second in a series of short videos. They feature Blake Mizerany
discussing Sinatra and Heroku in great technical detail at September’s
[Boston.rb](http://bostonrb.org). Watch [Part
1](https://thoughtbot.com/blog/post/215005339/sinatra-at-boston-rb-part-1).

<object width="400" height="300">
  <param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=7108353&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1"
    />
  <embed src="http://vimeo.com/moogaloop.swf?clip_id=7108353&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1"
    type="application/x-shockwave-flash" width="400" height="300" />
</object>

In HD this time... watch out, the kid is learning!

## "use" is built-in

In this video, Blake extends his example code using Rack middleware from
[rack-contrib](http://github.com/rack/rack-contrib) called
[`Rack::AcceptFormat`](http://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/accept_format.rb):

> Adds a format extension at the end of the URI when there is none,
> corresponding to the mime-type given in the Accept HTTP header.

Example from the docs:

    GET /some/resource HTTP/1.1
    Accept: application/json

    GET /some/resource.json HTTP/1.1
    Accept: application/json

Blake says we can `use Rack::AcceptFormat` in our `config.ru` or in Sinatra,
depending on the situation.

This middleware will re-write
[`path_info`](http://rack.rubyforge.org/doc/classes/Rack/Request.html#M000227)

What's cool about this is Sinatra doesn't have to know about
`Rack::AcceptFormat`'s deeds making our work with content types easier. By the
time the request gets to Sinatra, ".json" has been added. Call it "just-in-time
routing".

## Rack Hoptoad

On the day Blake spoke at Boston.rb, he and I sat down to get [Rack
Hoptoad](http://github.com/atmos/rack-hoptoad) working on Heroku. Staying true
to the philosophy of [backing into
patterns](https://thoughtbot.com/blog/post/215005339/sinatra-at-boston-rb-part-1#backing-into-patterns),
we started with a bare-bones Rack app, then moved to Sinatra.

In both cases, we need to specify the gem in our `.gems` file:

    # http://docs.heroku.com/gems#overview
    rack_hoptoad

Rack:

    # config.ru
    require 'rack_hoptoad'

    use Rack::HoptoadNotifier, "123abc"
    run lambda { |env| fail "Fail!" }

Sinatra:

    # config.ru
    require 'rack_hoptoad'
    require 'example'

    use Rack::HoptoadNotifier, "1234"
    run Sinatra::Application

    # example.rb
    require 'sinatra'

    configure :production do
      enable :raise_errors
    end

    get '/boom' do
      fail "Fail from Sinatra!"
    end

## When Rack, when Sinatra

Blake's rule of thumb is to start with Rack when he knows, when he's starting,
that he's only going to have one route, maybe two, and there's nothing special
about them.

In many ways, Sinatra is just a clean DSL around HTTP with lots of delegation
to Rack. Without it, you'd have messy conditional statements that are fine for
a couple of routes, but get out of hand beyond that.

## Routing tricks

Access wildcard operators using block syntax instead of a Rails-style
`params[:first_name]`:

    get '/:first_name/:last_name' do |first, last|
      "Hello, #{first} #{last}"
    end

Sinatra allows splats, such as this non-greedy match:

    get '/:name.*?/:last' do
    end

The returned object will be a normal Ruby
[MatchData](http://www.ruby-doc.org/core/classes/MatchData.html) object, so
everything you can do with that applies in your Sinatra code.

## next

Stay tuned next time when our protagonist discusses:

* POSTing data to a legacy API
* war stories
* view templates
