Inductor2010-12-29T22:58:39+01:00http://inductor.induktiv.at/Michael Raidelraidel@induktiv.atBundler and different platforms for development and production2010-12-29T00:00:00+01:00http://inductor.induktiv.at//blog/2010/12/29/bundler-and-different-platforms
<p>With the current version of Bundler (1.0.7) you have to watch out for platform specific gems when using different platforms for development and production. Bundler generates the lockfile (Gemfile.lock) with the specific version for the current platform which is ignored when using “bundle install” with the –deployment flag.</p>
<h3>Workarounds</h3>
<p>You could either not check in Gemfile.lock (not recommended) or not use the –deployment flag on deployment (which is used by default by bundlers’s capistrano recipe).</p>
<div class="highlight"><pre> <span class="c1"># override the bundler flags in a capistrano deployment</span>
<span class="c1"># config/deploy.rb</span>
<span class="nb">require</span> <span class="s2">"bundler/capistrano"</span>
<span class="n">set</span> <span class="ss">:bundle_flags</span><span class="p">,</span> <span class="s2">"--quiet"</span>
</pre>
</div>
<p>Alternatively you could update the lockfile on all used platforms by doing “bundle install” on each of them and commit the updated version (only works if the bundle is not already frozen which you can check with “bundle config”). Bundler keeps adding the additional gems to the lockfile and doesn’t overwrite the gems of another platform.</p>
Callbacks outside of the database transaction2010-09-01T00:00:00+02:00http://inductor.induktiv.at//blog/2010/09/01/after-commit-callbacks
<p>Callbacks are a fantastic way to trigger behaviour at a specific time in the lifecycle of an ActiveRecord object. If for example you want to do something before every save you would use the before_save callback. All of these callbacks run inside of a transaction which ensures data integrity. If something goes wrong, everything is rolled back.</p>
<h3>The problem</h3>
<p>But there are some cases where you want to run the callback after the transaction is committed. One example are expensive operations like image thumbnailing which would block the transaction too long. Another example is asynchronous processing in a queue. In an application which is using resque as the queueing system I just had the problem that every once in a while a job failed because the ActiveRecord object could not be found. The reason for this was the transaction: the resque job was queued in an after_create callback and in some rare cases the resque worker started the job faster than the database could finish the transaction! This could also happen when updating a search index or in any other task which depends on the updated state of the database.</p>
<h3>The solution</h3>
<p>In Rails 3 we can use the after_commit callbacks, which are triggered right after the commit of the transaction.</p>
<div class="highlight"><pre> <span class="c1"># triggers after the commit of every save</span>
<span class="n">after_commit</span> <span class="ss">:method_name</span>
<span class="c1"># triggers after the commit of a create</span>
<span class="n">after_commit</span> <span class="ss">:method_name</span><span class="p">,</span> <span class="ss">:on</span> <span class="o">=></span> <span class="ss">:create</span>
<span class="c1"># triggers after the commit of an update</span>
<span class="n">after_commit</span> <span class="ss">:method_name</span><span class="p">,</span> <span class="ss">:on</span> <span class="o">=></span> <span class="ss">:update</span>
<span class="c1"># triggers after the commit of a destroy</span>
<span class="n">after_commit</span> <span class="ss">:method_name</span><span class="p">,</span> <span class="ss">:on</span> <span class="o">=></span> <span class="ss">:destroy</span>
</pre>
</div>
<h3>When using Rails 2</h3>
<p>As the application I am working on is still on Rails 2.3 I am now using the <a href="http://github.com/freelancing-god/after_commit">after_commit</a> gem which provides this functionality with a slightly different syntax also for earlier versions of Rails (for all versions between 1.2 and 2.3).</p>
<div class="highlight"><pre> <span class="c1"># triggers after the commit of every save</span>
<span class="n">after_commit</span> <span class="ss">:method_name</span>
<span class="c1"># triggers after the commit of a create</span>
<span class="n">after_commit_on_create</span> <span class="ss">:method_name</span>
<span class="c1"># triggers after the commit of an update</span>
<span class="n">after_commit_on_update</span> <span class="ss">:method_name</span>
<span class="c1"># triggers after the commit of a destroy</span>
<span class="n">after_commit_on_destroy</span> <span class="ss">:method_name</span>
</pre>
</div>
<h3>Callbacks for rollback</h3>
<p>Both the after_commit gem and Rails 3 are also providing additional callbacks which trigger on a rollback of the transaction. These callbacks could be very useful for cleaning up things outside of the database.</p>
<div class="highlight"><pre> <span class="n">after_rollback</span> <span class="ss">:method_name</span>
</pre>
</div>
Mount Rack apps in Rails 32010-05-23T00:00:00+02:00http://inductor.induktiv.at//blog/2010/05/23/mount-rack-apps-in-rails-3
<p>The routing in Rails 3 (powered by the rack-mount gem) offers a lot of improvements in functionality and syntax over the Rails 2 style. You can read up about them in the following posts:</p>
<ul>
<li><a href="http://www.railsdispatch.com/posts/rails-routing">The Powerful New Rails Router</a></li>
<li><a href="http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/">The Rails 3 Router: Rack it Up</a></li>
</ul>
<p>One of the biggest improvements is the possibility to associate arbitrary rack apps with a specific route. There are different methods to configure the use of a Rack app in the router. One of them is the “match” method, which allows to map a path to a rack endpoint. The most common use of “match” is to specify a Rails controller and action (which can act like a rack app in Rails 3):</p>
<div class="highlight"><pre><span class="n">match</span> <span class="s2">"/blog"</span> <span class="o">=></span> <span class="s2">"articles#index"</span>
</pre>
</div>
<p>But instead of an action we also can route to any other rack app:</p>
<div class="highlight"><pre><span class="c1"># using a proc as an example for the most simple rack app</span>
<span class="n">match</span> <span class="s2">"/blog"</span> <span class="o">=></span> <span class="nb">proc</span> <span class="p">{</span> <span class="o">|</span><span class="n">env</span><span class="o">|</span> <span class="o">[</span> <span class="mi">200</span><span class="p">,</span> <span class="p">{},</span> <span class="o">[</span> <span class="s2">"my posts"</span> <span class="o">]</span> <span class="o">]</span> <span class="p">}</span>
<span class="c1"># or a class representing a rack app</span>
<span class="n">match</span> <span class="s2">"/blog"</span> <span class="o">=></span> <span class="no">MySinatraBlogApp</span>
<span class="c1"># with a glob to catch deeper nested routes</span>
<span class="n">match</span> <span class="s2">"/blog(/*other_params)"</span> <span class="o">=></span> <span class="no">MySinatraBlogApp</span>
</pre>
</div>
<p>You still have to do special work for the parts of the path following the “/blog”-prefix (for example specifying a glob so that the router knows to send requests looking like “/blog/archives” to the rack app). But the biggest disadvantage of this approach is that the Rack app has to know this path and use it in its own path recognition. In a request with the path “/blog/archives” the Sinatra app would look like this:</p>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">MySinatraBlogApp</span> <span class="o"><</span> <span class="no">Sinatra</span><span class="o">::</span><span class="no">Base</span>
<span class="n">get</span> <span class="s2">"/blog/archives"</span> <span class="k">do</span>
<span class="s2">"my old posts"</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<h3>Anchors</h3>
<p>Both problems can be solved by not “anchoring” the route. In the background a path given to “match” is converted to a regular expression by rack-mount. For “/blog” this expression would be /\A\/blog\Z/. The \A and \Z ensure that the path matches exactly and has no additional parts before or after the given route. If we don’t anchor the path the expression would be /\A\/blog/ allowing arbitrary paths after the “/blog”-prefix. Exactly what we want when mounting a rack app! Even better is that the PATH_INFO given to the rack app doesn’t include the prefix anymore which means that the app doesn’t have to know about the mount path.</p>
<div class="highlight"><pre><span class="n">match</span> <span class="s2">"/blog"</span> <span class="o">=></span> <span class="no">MySinatraBlogApp</span><span class="p">,</span> <span class="ss">:anchor</span> <span class="o">=></span> <span class="kp">false</span>
<span class="c1"># now the sinatra app for /blog/archives can look like this</span>
<span class="k">class</span> <span class="nc">MySinatraBlogApp</span> <span class="o"><</span> <span class="no">Sinatra</span><span class="o">::</span><span class="no">Base</span>
<span class="n">get</span> <span class="s2">"/archives"</span> <span class="k">do</span>
<span class="s2">"my old posts"</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<h3>Mount</h3>
<p>There also is a routing method doing this configuration for us which is unsurprisingly named “mount”:</p>
<div class="highlight"><pre><span class="n">mount</span> <span class="no">MySinatraBlogApp</span><span class="p">,</span> <span class="ss">:at</span> <span class="o">=></span> <span class="s2">"/blog"</span>
<span class="c1"># or simply</span>
<span class="n">mount</span> <span class="no">MySinatraBlogApp</span> <span class="o">=></span> <span class="s2">"/blog"</span>
</pre>
</div>
<p>The definition is the other way round than when using match and the anchor option is set to false automatically (mount uses match behind the scenes).</p>
<h3>Using the prefix in the rack app</h3>
<p>How does the rack app know about the prefix (for example necessary to generate correct urls)? It can use the “SCRIPT_NAME” environment variable which is set to the prefix automatically. There is one problem left when using Sinatra as the rack-app: for the root-path (/blog) the PATH_INFO in the environment is set to “” instead of just “/”. This way Sinatra will not recognize the request if its action is defined with a “/”. Instead you would have to use an empty string at the moment!</p>