<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 <title>Sinatra</title>
 <link href="http://sinatra.guthub.com/feed.xml" rel="self"/>
 <link href="http://sinatra.github.com/"/>
 <updated>2012-05-06T10:47:19-07:00</updated>
 <id>http://sinatrarb.com/</id>

 
 <entry>
   <title>New feature release, Contrib and Recipes</title>
   <link href="http://sinatra.github.com/2011/09/30/sinatra-1.3.0.html"/>
   <published>2011-09-30T00:00:00-07:00</published>
   <updated>2011-09-30T00:00:00-07:00</updated>
   <author>
     <name>Konstantin Haase</name>
     <uri>http://rkh.im</uri>
   </author>
   <id>http://sinatrarb.com/2011/09/30/sinatra-1.3.0</id>
   <content type="html">&lt;p&gt;We&amp;#8217;re proud to announce two new releases today: 1.3.0 and 1.2.7. We&amp;#8217;re also simultaneously releasing sinatra-contrib and would like to officially announce the recently launched Sinatra Recipes project. Read on for more goodness!&lt;/p&gt;

&lt;h2 id='sinatra_130'&gt;Sinatra 1.3.0&lt;/h2&gt;

&lt;p&gt;We have a new feature release!&lt;/p&gt;

&lt;p&gt;From our perspective, one of the biggest additions is a streaming API. A simple version of it ships with Sinatra directly and is extended in sinatra-contrib. The vanilla version looks like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;get &amp;#39;/&amp;#39; do
  stream do |out|
    out &amp;lt;&amp;lt; &amp;quot;It&amp;#39;s gonna be legen -\n&amp;quot;
    sleep 0.5
    out &amp;lt;&amp;lt; &amp;quot; (wait for it) \n&amp;quot;
    sleep 1
    out &amp;lt;&amp;lt; &amp;quot;- dary!\n&amp;quot;
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The cool thing about this is that it abstracts away the differences between all the different Rack servers, no matter if those are evented (like Thin, Rainbows! or Ebb) or sequential (like Unicorn, Passenger or Mongrel). Only WEBRick has issues with it at the moment (you&amp;#8217;ll get the response body all at once), but we are looking into this.&lt;/p&gt;

&lt;p&gt;What is really interesting about this: If you run on an evented server, like Thin, you can keep the connection open and easily implement messaging services, Server-Sent Events and so on:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;set :server, :thin
connections = []

get &amp;#39;/&amp;#39; do
  # keep stream open
  stream(:keep_open) { |out| connections &amp;lt;&amp;lt; out }
end

post &amp;#39;/&amp;#39; do
  # write to all open streams
  connections.each { |out| out &amp;lt;&amp;lt; params[:message] &amp;lt;&amp;lt; &amp;quot;\n&amp;quot; }
  &amp;quot;message sent&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It is worth mentioning that all this works without fibers (which, amongst other things, would significantly limit the stack size).&lt;/p&gt;

&lt;p&gt;We added support for the PATCH HTTP verb, which you might be familiar with from the new GitHub API:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;patch &amp;#39;/&amp;#39; do
  # ... modify a resource ...
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A &lt;code&gt;logger&lt;/code&gt; helper for logging is available now, and if it writes to the logs depends on whether you enabled or disabled logging:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;configure(:test) { disable :logging }

get &amp;#39;/&amp;#39; do
  logger.info &amp;quot;I just want to let you know: I&amp;#39;ll take care of the request!&amp;quot;
  &amp;quot;Hello World!&amp;quot;
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;erubis&lt;/code&gt; method has been deprecated. Sinatra will automatically use Erubis for rendering ERB templates if available.&lt;/p&gt;

&lt;p&gt;There is more coming with this release, but the rest is mainly bug fixes and improving the behavior. For instance, Sinatra treats ETags and Last-Modified headers properly when they are used as optimistic locking for unsafe HTTP verbs. For more changes, see the 1.3.0 &lt;a href='https://github.com/sinatra/sinatra/blob/v1.3.0/CHANGES'&gt;change log&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Special thanks for helping with the 1.3.0 release go to:&lt;/p&gt;

&lt;p&gt;Gabriel Andretta, michelc, burningTyger, Tim Felgentreff, Vasily Polovnyov, nashby, kenichi nakamura, Gaku Ueda, Gabriel Horner, Sylvain Desvé, Jacob Burkhart &amp;amp; Josh Lane, aibo (irc), Selman ULUG, Aviv Ben-Yosef, Paolo &amp;#8220;Nusco&amp;#8221; Perrotta, Marcos Toledo, Matthew Schinckel, Tim Preston, Davide D&amp;#8217;Agostino, Simone Carletti, Peter Suschlik, Postmodern, F. Zhang, Rémy Coutable, and David Waite&lt;/p&gt;

&lt;h2 id='sinatra_127'&gt;Sinatra 1.2.7&lt;/h2&gt;

&lt;p&gt;We will drop support for Rack prior to 1.3 and Ruby 1.8.6 with the Sinatra 1.3.0 release. However, we will continue to supply Sinatra 1.2 with bug fixes until the End-Of-Life of Rack 1.2.x and Sinatra 1.2 will always remain compatible with the latest released 1.8.6 patchlevel.&lt;/p&gt;

&lt;p&gt;For the backported patches, see the 1.2.7 &lt;a href='https://github.com/sinatra/sinatra/blob/v1.2.7/CHANGES'&gt;change log&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;d like to thank everyone helping with the 1.2.7 release:&lt;/p&gt;

&lt;p&gt;Emanuele Vicentini, Takanori Ishikawa, David Kellum, Gaku Ueda, Lee Reilly, Iain Barnett, pete, Luke Jahnke, John Wolfe, Andrew Armenia, Tim Felgentreff, and Alessandro Dal Grande&lt;/p&gt;

&lt;h2 id='sinatracontrib'&gt;Sinatra-Contrib&lt;/h2&gt;

&lt;p&gt;There are a lot of Sinatra extensions out there, and some of those are used by a large number of apps, like sinatra-content-for or sinatra-reloader. The maintainers of these extensions have to keep up with new Sinatra releases to make sure everything works fine. This poses an issue from time to time, esp. since some of these extensions were relying on Sinatra internals. To fix this, we created the sinatra-contrib project (source code at https://github.com/sinatra/sinatra-contrib). This project contains a number of extensions that are probably useful for most Sinatra applications. Some are old extensions that have largely been rewritten to ensure the code quality developers are used to from Sinatra itself and to no longer rely on internals, like sinatra-namespace, and some are new additions of general interest, for example sinatra-respond-with.&lt;/p&gt;

&lt;p&gt;Here is the promise: For every Sinatra release, starting with 1.3.0, there will &lt;em&gt;always&lt;/em&gt; be a fully compatible sinatra-contrib release. Documentation for all the extensions shipping with sinatra-contrib will be made available on the Sinatra website. I would not have managed to take care of this all by my self, so I&amp;#8217;m really grateful that Gabriel Andretta jumped in to help with this project.&lt;/p&gt;

&lt;p&gt;Documentation is available at http://www.sinatrarb.com/contrib.&lt;/p&gt;

&lt;h2 id='sinatra_recipes'&gt;Sinatra Recipes&lt;/h2&gt;

&lt;p&gt;Zachary Scott recently launched the the &lt;a href='http://recipes.sinatrarb.com/'&gt;Recipes&lt;/a&gt; project. It contains community contributed recipes and techniques for Sinatra.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Sinatra Loves Dancer</title>
   <link href="http://sinatra.github.com/2011/07/21/sinatra-loves-dancer.html"/>
   <published>2011-07-21T00:00:00-07:00</published>
   <updated>2011-07-21T00:00:00-07:00</updated>
   <author>
     <name>Konstantin Haase</name>
     <uri>http://rkh.im</uri>
   </author>
   <id>http://sinatrarb.com/2011/07/21/sinatra-loves-dancer</id>
   <content type="html">&lt;p&gt;&lt;em&gt;&amp;#8220;The only cool PR is provided by one&amp;#8217;s enemies. They toil incessantly and for free.&amp;#8221; - Marshall McLuhan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are &lt;a href='http://en.wikipedia.org/wiki/Sinatra_%28software%29#Sinatra_inspired_frameworks'&gt;a lot of frameworks&lt;/a&gt; out there inspired by Sinatra. One of them is &lt;a href='http://www.perldancer.org/'&gt;Dancer&lt;/a&gt;. Some unknown individual or group was posing as different members of the Sinatra core team on &lt;a href='http://cpanratings.perl.org/dist/Dancer'&gt;CPAN ratings&lt;/a&gt;, a website to comment on the quality of Perl libraries.&lt;/p&gt;

&lt;p&gt;Those comments were extremely rude and do not represent the opinion of any of the Sinatra developers. Quite the opposite, we love how Sinatra inspired so many of the libraries and are even proud to see Dancer being adopted by Perl developers.&lt;/p&gt;

&lt;p&gt;We do not know what the agenda of this one individual is, and honestly, we do not care. The harm done by this person to the Dancer project, the Sinatra project and the people he posed as is unacceptable. The incident has been reported to the CPAN ratings team and we hope that those comments will be removed in due time.&lt;/p&gt;

&lt;p&gt;If you are a Perl developer, we suggest you check out Dancer.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>What's New in Sinatra 1.2?</title>
   <link href="http://sinatra.github.com/2011/03/03/sinatra-1.2.0.html"/>
   <published>2011-03-03T00:00:00-08:00</published>
   <updated>2011-03-03T00:00:00-08:00</updated>
   <author>
     <name>Konstantin Haase</name>
     <uri>http://rkh.im</uri>
   </author>
   <id>http://sinatrarb.com/2011/03/03/sinatra-1.2.0</id>
   <content type="html">&lt;p&gt;As announced on the &lt;a href='http://groups.google.com/group/sinatrarb/browse_thread/thread/515d1a5bf70b10a1'&gt;mailing list&lt;/a&gt;, we have just released &lt;a href='https://rubygems.org/gems/sinatra/versions/1.2.0'&gt;Sinatra 1.2.0&lt;/a&gt;. Let&amp;#8217;s have a closer look at the new features.&lt;/p&gt;

&lt;h2 id='slim_support'&gt;Slim support&lt;/h2&gt;

&lt;p&gt;Sinatra now supports the &lt;a href='http://slim-lang.com/'&gt;Slim Template Engine&lt;/a&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;slim&amp;#39;&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;slim&lt;/span&gt; &lt;span class='ss'&gt;:index&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;

&lt;span class='cp'&gt;__END__&lt;/span&gt;

&lt;span class='cp'&gt;@@ index&lt;/span&gt;
&lt;span class='cp'&gt;! doctype html&lt;/span&gt;
&lt;span class='cp'&gt;html&lt;/span&gt;
&lt;span class='cp'&gt;  head&lt;/span&gt;
&lt;span class='cp'&gt;    title Sinatra With Slim&lt;/span&gt;
&lt;span class='cp'&gt;  body&lt;/span&gt;
&lt;span class='cp'&gt;    h1 Slim Is Fun!&lt;/span&gt;
&lt;span class='cp'&gt;    a href=&amp;quot;http://haml-lang.com/&amp;quot; A bit like Haml, don&amp;#39;t you think?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='inline_markaby'&gt;Inline Markaby&lt;/h2&gt;

&lt;p&gt;Like Builder and Nokogiri templates, &lt;a href='http://markaby.rubyforge.org/'&gt;Markaby&lt;/a&gt; can now be used directly inline:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;markaby&amp;#39;&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;markaby&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='n'&gt;html&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
      &lt;span class='n'&gt;head&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;title&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Sinatra With Markaby&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
      &lt;span class='n'&gt;body&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;h1&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;Markaby Is Fun!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
    &lt;span class='k'&gt;end&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='layout_engines'&gt;Layout Engines&lt;/h2&gt;

&lt;p&gt;Whenever you render a template, like &lt;code&gt;some_page.haml&lt;/code&gt;, Sinatra will use a corresponding layout, like &lt;code&gt;layout.haml&lt;/code&gt; for you. With the &lt;code&gt;:layout&lt;/code&gt; option it has always been possible to use a different layout, but it still had to be written in the same template language, Haml in our example. In 1.1 we introduced &lt;code&gt;markdown&lt;/code&gt;, &lt;code&gt;textile&lt;/code&gt; and &lt;code&gt;rdoc&lt;/code&gt; templates. It is not possible to use those for layouts. We therefore added the &lt;code&gt;:layout_engine&lt;/code&gt; option, which easily allows you to combine one two different template engines:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra&amp;#39;&lt;/span&gt;
&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;rdiscount&amp;#39;&lt;/span&gt;

&lt;span class='c1'&gt;# for all markdown files, use post.haml as layout&lt;/span&gt;
&lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:markdown&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:layout_engine&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:haml&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:layout&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:post&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c1'&gt;# use index.haml for readme&lt;/span&gt;
  &lt;span class='n'&gt;markdown&lt;/span&gt; &lt;span class='ss'&gt;:README&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:layout&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:index&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/:post&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;markdown&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:post&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;to_sym&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This feature should also be handy when migrating from one template language to another, as it allows you to combine Erb with Haml, for instance.&lt;/p&gt;

&lt;h2 id='conditional_filters'&gt;Conditional Filters&lt;/h2&gt;

&lt;p&gt;We introduced pattern matching filters in 1.1. Now they also support conditions:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;before&lt;/span&gt; &lt;span class='ss'&gt;:agent&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='sr'&gt;/Song Bird/&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c1'&gt;# ...&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Those can also be combined with patterns, of course:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;after&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/api/*&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:provides&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='ss'&gt;:json&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c1'&gt;# ...&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='url_helper'&gt;URL helper&lt;/h2&gt;

&lt;p&gt;Usually Sinatra does not provide any view helper methods. Those are provided by extensions and would not suit Sinatra&amp;#8217;s approach of a small but robust core. However, constructing URLs is a use case most people run in sooner or later. It is a bit complicated to construct URLs right. Consider this example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;lt;a href=&amp;#39;/bar&amp;#39;&amp;gt;Will you make it?&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;You made it!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Feel free to run it. Works, doesn&amp;#8217;t it? So, what is wrong with it?&lt;/p&gt;

&lt;p&gt;Imagine your app is &amp;#8220;mounted&amp;#8221; by another Rack application, for instance in a &lt;code&gt;config.ru&lt;/code&gt; like this:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/there&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='no'&gt;Sinatra&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Application&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;map&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;run&lt;/span&gt; &lt;span class='no'&gt;MyRailsApp&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Application&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now the link to &lt;code&gt;/bar&lt;/code&gt; would end up in a request send to &lt;code&gt;MyRailsApp&lt;/code&gt; rather than to Sinatra. Injecting &lt;code&gt;request.script_name&lt;/code&gt; would fix this, but be honest, how often do you do that?&lt;/p&gt;

&lt;p&gt;Now, imagine these links are presented out of context, in an RSS feed or embedded on another host. In that case you might want to construct absolute URLs. This is even more cumbersome, as you most certainly either forget to handle reverse proxies, alternative ports/protocols or you end up with lots of URL related code all over the place, while what you should do is use the &lt;code&gt;url&lt;/code&gt; helper:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;lt;a href=&amp;#39;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;url&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;#39;&amp;gt;You will make it!&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;You made it!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Since you are likely going to use this with redirects, we also aliased the helper to &lt;code&gt;to&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;redirect&lt;/span&gt; &lt;span class='n'&gt;to&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;You made it!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='named_captures_on_19'&gt;Named Captures on 1.9&lt;/h2&gt;

&lt;p&gt;Ruby 1.9 introduced &lt;a href='http://ruby.runpaint.org/regexps#captures'&gt;named captures&lt;/a&gt; for regular expressions. Sinatra accepts regular expressions for matching paths. Now named captures will automatically end up populating &lt;code&gt;params&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='sr'&gt;%r{/(?&amp;lt;year&amp;gt;\d{4})/(?&amp;lt;month&amp;gt;\d{2})/(?&amp;lt;day&amp;gt;\d{2})/?}&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;date&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Date&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;new&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:year&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;to_i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:month&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;to_i&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:day&lt;/span&gt;&lt;span class='o'&gt;].&lt;/span&gt;&lt;span class='n'&gt;to_i&lt;/span&gt;
  &lt;span class='vi'&gt;@posts&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;pubished_on&lt;/span&gt; &lt;span class='n'&gt;date&lt;/span&gt;
  &lt;span class='n'&gt;erb&lt;/span&gt; &lt;span class='ss'&gt;:posts&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='templates_with_different_scopes'&gt;Templates with different scopes&lt;/h2&gt;

&lt;p&gt;All rendering methods now accept a &lt;code&gt;:scope&lt;/code&gt; options:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/:id&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='nb'&gt;id&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
  &lt;span class='vi'&gt;@post&lt;/span&gt; &lt;span class='o'&gt;=&lt;/span&gt; &lt;span class='no'&gt;Post&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;find&lt;/span&gt; &lt;span class='nb'&gt;id&lt;/span&gt;

  &lt;span class='c1'&gt;# without scope&lt;/span&gt;
  &lt;span class='n'&gt;erb&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;lt;%= @post.name %&amp;gt;&amp;quot;&lt;/span&gt;

  &lt;span class='c1'&gt;# with scope&lt;/span&gt;
  &lt;span class='n'&gt;erb&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&amp;lt;%= name %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:scope&lt;/span&gt; &lt;span class='o'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='vi'&gt;@post&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Note that all Sinatra helper methods and instance variables will &lt;em&gt;not&lt;/em&gt; be available.&lt;/p&gt;

&lt;h2 id='configurable_redirects'&gt;Configurable redirects&lt;/h2&gt;

&lt;p&gt;In 1.1 we made sure all redirects were absolute URIs, to conform with RFC 2616 (HTTP 1.1). This will result in issues for you, if you have a broken Reverse Proxy configuration. If so, you should really fix your configuration. If you are unable to do so, a simple &lt;code&gt;disable :absolute_redirects&lt;/code&gt; will now give you back the 1.0 behavior. As shown above, you can now use the &lt;code&gt;to&lt;/code&gt; helper with redirect. If all your redirects are application local, you can now &lt;code&gt;enable :prefixed_redirects&lt;/code&gt; and skip the &lt;code&gt;to&lt;/code&gt; altogether:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;enable&lt;/span&gt; &lt;span class='ss'&gt;:prefixed_redirects&lt;/span&gt;
&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/foo&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='n'&gt;redirect&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='n'&gt;get&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s1'&gt;&amp;#39;/bar&amp;#39;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;You made it!&amp;quot;&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We did not enable this per default to not break compatibility and to allow you redirects to other Rack endpoints.&lt;/p&gt;

&lt;h2 id='overriding_template_lookup'&gt;Overriding template lookup&lt;/h2&gt;

&lt;p&gt;One popular feature request is supporting multiple view folders. But everyone wants different semantics. So, instead of choosing one way to go, we gave you means to implement your own lookup logic:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;helpers&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;find_template&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;looking for index.txt&amp;quot;&lt;/span&gt;
    &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;views/index.txt&amp;quot;&lt;/span&gt;
    &lt;span class='nb'&gt;puts&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;apparently, index.txt doesn&amp;#39;t exist, let&amp;#39;s try index.html&amp;quot;&lt;/span&gt;
    &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;views/index.html&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;/&amp;quot;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;haml&lt;/span&gt; &lt;span class='ss'&gt;:foo&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sinatra will call &lt;code&gt;find_template&lt;/code&gt; to discover the template file. In the above example, we don&amp;#8217;t care about what template engine to use or what name the template has. It will use &lt;code&gt;views/index.txt&lt;/code&gt; or &lt;code&gt;views/index.html&lt;/code&gt; for every template. Let&amp;#8217;s have a look at the standard implementation:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;find_template&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;views&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;engine&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='no'&gt;Tilt&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;mappings&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;each&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt; &lt;span class='o'&gt;|&lt;/span&gt;&lt;span class='n'&gt;ext&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='n'&gt;klass&lt;/span&gt;&lt;span class='o'&gt;|&lt;/span&gt;
    &lt;span class='k'&gt;next&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='n'&gt;klass&lt;/span&gt; &lt;span class='o'&gt;==&lt;/span&gt; &lt;span class='n'&gt;engine&lt;/span&gt;
    &lt;span class='k'&gt;yield&lt;/span&gt; &lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;join&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;views&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='nb'&gt;name&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;.&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;ext&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, it will look in the views folder for a file named like the template with any of the file extensions registered for the template engine.&lt;/p&gt;

&lt;p&gt;If all you want to change is the folder, you probably should just call &lt;code&gt;super&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;find_template&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;views&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;super&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;views&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/a&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;super&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='s2'&gt;&amp;quot;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;views&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;/b&amp;quot;&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;*&lt;/span&gt;&lt;span class='n'&gt;a&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='o'&gt;&amp;amp;&lt;/span&gt;&lt;span class='n'&gt;b&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;More examples can be found in the &lt;a href='http://www.sinatrarb.com/intro#Looking%20Up%20Template%20Files'&gt;readme&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id='other_changes'&gt;Other changes&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;send_file&lt;/code&gt; now takes a &lt;code&gt;:last_modified&lt;/code&gt; option&lt;/li&gt;

&lt;li&gt;improved error handling&lt;/li&gt;
&lt;/ul&gt;</content>
 </entry>
 
 <entry>
   <title>Blog revived</title>
   <link href="http://sinatra.github.com/2011/03/03/blog-revived.html"/>
   <published>2011-03-03T00:00:00-08:00</published>
   <updated>2011-03-03T00:00:00-08:00</updated>
   <author>
     <name>Konstantin Haase</name>
     <uri>http://rkh.im</uri>
   </author>
   <id>http://sinatrarb.com/2011/03/03/blog-revived</id>
   <content type="html">&lt;p&gt;It has been quiet on this blog recently. Announcements, like the 1.0 and 1.1 releases have only been made on the mailing list. Plans are to change this and accompany mailing list announcements with in-depth articles about new feature releases.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>We Have a FAQ Now</title>
   <link href="http://sinatra.github.com/2009/01/29/we-have-a-faq-now.html"/>
   <published>2009-01-29T00:00:00-08:00</published>
   <updated>2009-01-29T00:00:00-08:00</updated>
   <author>
     <name>Ryan Tomayko</name>
     <uri>http://tomayko.com/about</uri>
   </author>
   <id>http://sinatrarb.com/2009/01/29/we-have-a-faq-now</id>
   <content type="html">&lt;p&gt;Just getting started with Sinatra and wondering how to do something that should be obvious? &lt;a href='/faq.html'&gt;Check out The FAQ&lt;/a&gt;. We culled a few weeks worth of IRC logs and mailing list threads to compile the initial set of entries and we&amp;#8217;ll be adding to the list considerably over the coming weeks.&lt;/p&gt;

&lt;p&gt;Have an idea for a FAQ entry? Fork the &lt;a href='http://github.com/sinatra/sinatra.github.com/'&gt;sinatra.github.com repository&lt;/a&gt;, add the entry to &lt;code&gt;faq.markdown&lt;/code&gt;, and push. We&amp;#8217;ll take care of the rest.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>What's New in Sinatra 0.9.0</title>
   <link href="http://sinatra.github.com/2009/01/18/sinatra-0.9.0.html"/>
   <published>2009-01-18T00:00:00-08:00</published>
   <updated>2009-01-18T00:00:00-08:00</updated>
   <author>
     <name>Ryan Tomayko</name>
     <uri>http://tomayko.com/about</uri>
   </author>
   <id>http://sinatrarb.com/2009/01/18/sinatra-0.9.0</id>
   <content type="html">&lt;p&gt;This is the first in a series of 0.9.x releases designed to move Sinatra toward a rock solid 1.0. While we were able to add a touch of new hotness in this release, the major focus has been on getting the codebase shaped up for future development. Many longstanding bugs and minor annoyances were corrected along the way.&lt;/p&gt;

&lt;p&gt;Sinatra&amp;#8217;s internal classes and methods have changed significantly in this release. Most apps written for 0.3.x will work just fine under the new codebase but we&amp;#8217;ve begun adding deprecation warnings for things slated to be ripped out completely in 1.0. &lt;strong&gt;Please test your apps before upgrading production environments to the 0.9.0 gem.&lt;/strong&gt; We&amp;#8217;re committed to keeping existing apps running through 0.9.x so report compatibility issues through &lt;a href='/contributing.html'&gt;the normal channels&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With that out of the way, here are some of the new features to look out for in 0.9.0.&lt;/p&gt;

&lt;h2 id='sinatrabase_and_proper_rack_citizenship'&gt;Sinatra::Base and Proper Rack Citizenship&lt;/h2&gt;

&lt;p&gt;Sinatra can now be used to build modular / reusable &lt;a href='http://rack.rubyforge.org/'&gt;Rack&lt;/a&gt; applications and middleware components. This means that multiple Sinatra applications can now be run in isolation and co-exist peacefully with other Rack based frameworks.&lt;/p&gt;

&lt;p&gt;Requiring &lt;code&gt;&amp;#39;sinatra/base&amp;#39;&lt;/code&gt; instead of &lt;code&gt;&amp;#39;sinatra&amp;#39;&lt;/code&gt; causes a subset of Sinatra&amp;#8217;s features to be loaded. No methods are added to the top-level and the command-line / auto-running features are disabled. Subclassing &lt;code&gt;Sinatra::Base&lt;/code&gt; creates a Rack component with the familiar Sinatra DSL methods available in class scope. These classes can then be run as Rack applications or used as middleware components.&lt;/p&gt;

&lt;p&gt;Proper documentation on this feature is in the works but here&amp;#8217;s a quick example for illustration:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='nb'&gt;require&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;sinatra/base&amp;#39;&lt;/span&gt;

&lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Foo&lt;/span&gt; &lt;span class='o'&gt;&amp;lt;&lt;/span&gt; &lt;span class='no'&gt;Sinatra&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Base&lt;/span&gt;
  &lt;span class='c1'&gt;# all options are available for the setting:&lt;/span&gt;
  &lt;span class='n'&gt;enable&lt;/span&gt; &lt;span class='ss'&gt;:static&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='ss'&gt;:session&lt;/span&gt;
  &lt;span class='n'&gt;set&lt;/span&gt; &lt;span class='ss'&gt;:root&lt;/span&gt;&lt;span class='p'&gt;,&lt;/span&gt; &lt;span class='no'&gt;File&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;dirname&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='bp'&gt;__FILE__&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;

  &lt;span class='c1'&gt;# each subclass has its own private middleware stack:&lt;/span&gt;
  &lt;span class='n'&gt;use&lt;/span&gt; &lt;span class='no'&gt;Rack&lt;/span&gt;&lt;span class='o'&gt;::&lt;/span&gt;&lt;span class='no'&gt;Deflator&lt;/span&gt;

  &lt;span class='c1'&gt;# instance methods are helper methods and are available from&lt;/span&gt;
  &lt;span class='c1'&gt;# within filters, routes, and views:&lt;/span&gt;
  &lt;span class='k'&gt;def&lt;/span&gt; &lt;span class='nf'&gt;em&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;&amp;lt;em&amp;gt;&lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;text&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;&amp;lt;/em&amp;gt;&amp;quot;&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;

  &lt;span class='c1'&gt;# routes are defined as usual:&lt;/span&gt;
  &lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/hello/:person&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
    &lt;span class='s2'&gt;&amp;quot;Hello &amp;quot;&lt;/span&gt; &lt;span class='o'&gt;+&lt;/span&gt; &lt;span class='n'&gt;em&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:person&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='k'&gt;end&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That thing can be plugged in anywhere along a Rack pipeline. For instance, once Rails 2.3 ships, you&amp;#8217;ll be able to use Sinatra apps to build &lt;a href='http://weblog.rubyonrails.org/2008/12/17/introducing-rails-metal'&gt;Rails Metal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Jesse Newland and Jon Crosby are &lt;a href='http://blog.joncrosby.me/post/72451217/a-world-of-middleware'&gt;already experimenting&lt;/a&gt;. Very hot.&lt;/p&gt;

&lt;h2 id='nested_params'&gt;Nested Params&lt;/h2&gt;

&lt;p&gt;Form parameters with subscripts are now parsed into a nested/recursive Hash structure. Here&amp;#8217;s a form:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='html'&gt;&lt;span class='nt'&gt;&amp;lt;form&lt;/span&gt; &lt;span class='na'&gt;method=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;POST&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;action=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;/guestbook/&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;input&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;text&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;person[name]&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;input&lt;/span&gt; &lt;span class='na'&gt;type=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;text&amp;#39;&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;person[email]&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&lt;/span&gt;
  &lt;span class='nt'&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class='na'&gt;name=&lt;/span&gt;&lt;span class='s'&gt;&amp;#39;note&amp;#39;&lt;/span&gt;&lt;span class='nt'&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class='nt'&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It looks like this on the wire:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;person[name]=Frank&amp;amp;person[email]=frank@theritz.com&amp;amp;message=Stay%20cool&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sinatra turns it into a nested Hash structure when accessed through the &lt;code&gt;params&lt;/code&gt; method:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;post&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/guestbook/&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:person&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;    &lt;span class='c1'&gt;# =&amp;gt; { :name =&amp;gt; &amp;#39;Frank&amp;#39;, :email =&amp;gt; &amp;#39;frank@theritz.com&amp;#39; }&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;Hi &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;person&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:name&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;! Thanks for signing my guestbook.&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This was a massively popular feature requests. Thanks to &lt;a href='http://foca.tumblr.com/'&gt;Nicolás Sanguinetti&lt;/a&gt; for the patch and &lt;a href='http://manveru.net/about_me'&gt;Michael Fellinger&lt;/a&gt; for the original implementation.&lt;/p&gt;

&lt;h2 id='routing_with_regular_expressions'&gt;Routing with Regular Expressions&lt;/h2&gt;

&lt;p&gt;The route declaration methods (&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;) now take a Regexp as a pattern. Captures are made available to the route block at &lt;code&gt;params[:captures]&lt;/code&gt;:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='sr'&gt;%r{/foo/(bar|baz)/(\d+)}&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='c1'&gt;# assuming: GET /foo/bar/42&lt;/span&gt;
  &lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:captures&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;  &lt;span class='c1'&gt;# =&amp;gt; [&amp;#39;bar&amp;#39;, 42]&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id='passing_on_a_route'&gt;Passing on a Route&lt;/h2&gt;

&lt;p&gt;We added a new request-level &lt;code&gt;pass&lt;/code&gt; method that immediately exits the current block and passes control to the next matching route. For example:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='ruby'&gt;&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/shoot/:person&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='n'&gt;pass&lt;/span&gt; &lt;span class='k'&gt;unless&lt;/span&gt; &lt;span class='sx'&gt;%w[Kenny Sherrif]&lt;/span&gt;&lt;span class='o'&gt;.&lt;/span&gt;&lt;span class='n'&gt;include?&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:person&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='p'&gt;)&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;You shot &lt;/span&gt;&lt;span class='si'&gt;#{&lt;/span&gt;&lt;span class='n'&gt;params&lt;/span&gt;&lt;span class='o'&gt;[&lt;/span&gt;&lt;span class='ss'&gt;:person&lt;/span&gt;&lt;span class='o'&gt;]&lt;/span&gt;&lt;span class='si'&gt;}&lt;/span&gt;&lt;span class='s2'&gt;.&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;

&lt;span class='n'&gt;get&lt;/span&gt; &lt;span class='s1'&gt;&amp;#39;/shoot/*&amp;#39;&lt;/span&gt; &lt;span class='k'&gt;do&lt;/span&gt;
  &lt;span class='s2'&gt;&amp;quot;Missed!&amp;quot;&lt;/span&gt;
&lt;span class='k'&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If no matching route is found after a &lt;code&gt;pass&lt;/code&gt;, a &lt;code&gt;NotFound&lt;/code&gt; exception is raised and the application 404s as if no route had matched in the first place.&lt;/p&gt;

&lt;h2 id='refined_test_framework'&gt;Refined Test Framework&lt;/h2&gt;

&lt;p&gt;Sinatra&amp;#8217;s testing support no longer depends on &lt;code&gt;Test::Unit&lt;/code&gt; (or any specific test framework for that matter). Requiring &lt;code&gt;&amp;#39;sinatra/test&amp;#39;&lt;/code&gt; brings in the &lt;a href='/api/classes/Sinatra/Test.html'&gt;&lt;code&gt;Sinatra::Test&lt;/code&gt; module&lt;/a&gt; and the &lt;a href='/api/classes/Sinatra/TestHarness.html'&gt;&lt;code&gt;Sinatra::TestHarness&lt;/code&gt; class&lt;/a&gt;, which can be used as necessary to simulate requests and make assertions about responses.&lt;/p&gt;

&lt;p&gt;You can also require &lt;code&gt;sinatra/test/unit&lt;/code&gt;, &lt;code&gt;sinatra/test/spec&lt;/code&gt;, &lt;code&gt;sinatra/test/rspec&lt;/code&gt;, or &lt;code&gt;sinatra/test/bacon&lt;/code&gt; to setup a framework-specific testing environment. See the section on &amp;#8220;Testing&amp;#8221; in the &lt;a href='/intro.html'&gt;&lt;code&gt;README&lt;/code&gt;&lt;/a&gt; for examples.&lt;/p&gt;

&lt;h2 id='more'&gt;More&lt;/h2&gt;

&lt;p&gt;See the &lt;a href='./changes.html'&gt;&lt;code&gt;CHANGES&lt;/code&gt;&lt;/a&gt; file for a comprehensive list of enhancements, bug fixes, and deprecations.&lt;/p&gt;</content>
 </entry>
 
</feed>

