<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[cesario's blog]]></title>
  <link href="http://franck.verrot.fr/atom.xml" rel="self"/>
  <link href="http://franck.verrot.fr/"/>
  <updated>2012-04-21T11:24:01+02:00</updated>
  <id>http://franck.verrot.fr/</id>
  <author>
    <name><![CDATA[Franck Verrot]]></name>
    <email><![CDATA[franck@verrot.fr]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Pitch, Business Model, People: my wrap up of the 3rd Startup Weekend Lyon]]></title>
    <link href="http://franck.verrot.fr/blog/2012/04/21/pitch--business-model--people--my-wrap-up-of-the-3rd-startup-weekend-lyon/"/>
    <updated>2012-04-21T00:00:00+02:00</updated>
    <id>http://franck.verrot.fr/blog/2012/04/21/pitch&#8211;business-model&#8211;people&#8211;my-wrap-up-of-the-3rd-startup-weekend-lyon</id>
    <content type="html"><![CDATA[<p>Last weekend I had my first Startup Weekend experience. I must admit I have always been skeptical about
this kind of events and came with two goals in mind: try to change my mind about it <strong>and</strong> pitch some idea
I had in the back of my head for a little while.</p>

<!--more-->


<p>The formula is quite simple yet efficient: 54 hours to bootstrap a startup. Participants are pitching the first evening,
then the audience decides what projects they want to see come to life during the weekend, and finally, teams are formed
out of this first session.</p>

<p>I came with the goal of not writing a line of code during this weekend because this is the kind of activity I could do
alone when the kids are asleep. I came to pitch an idea, understand the mechanics of writing a business model and meet people.</p>

<p>Those three goals have been reached.</p>

<ol>
<li>The Pitch: 60 seconds to convince people that my idea was awesome. I used to talk a lot in front of people (at previous jobs, at <a href="http://rulu.eu">conferences</a>, at <a href="http://lyonrb.fr">meetups</a> or small events like Code Retreats), so there was no stress doing it, but I kinda failed at explaining the vision in such a reduced timeframe.</li>
<li>The Business Model: I discovered a lot of tools (like the Lean Business Model Canvas). The tools alone are useless, and the mentoring from more experienced people in the team and from the mentors like Jerry Nieuviarts, from Clubic, or Thierry Boiron, from&#8230; Boiron (!), were more than welcome.</li>
<li>The People: From the participants to the mentors thru the organizers, the work environment was awesome. I was afraid by the spirit of competition, which often ruin the general atmosphere, but everything went just fine.</li>
</ol>


<p>As a conclusion, I&#8217;m definitely going to participate in the next sessions, and
probably not only in Lyon. I met good people, inspiring people, and the format
of the event is perfect to engage one&#8217;s attention on a single thing: bootstrap a startup.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ActiveValidators 1.9.0]]></title>
    <link href="http://franck.verrot.fr/blog/2012/04/07/activevalidators-190/"/>
    <updated>2012-04-07T00:00:00+02:00</updated>
    <id>http://franck.verrot.fr/blog/2012/04/07/activevalidators-190</id>
    <content type="html"><![CDATA[<p>ActiveValidators 1.9.0 is out!</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="n">install</span> <span class="n">activevalidators</span>
</span></code></pre></td></tr></table></div></figure>


<p>Read on for the full - yet concise - changelog.</p>

<!--more-->


<p>From its first versions, ActiveValidators has been designed to rely on the
<code>mail</code> gem. The <code>mail</code> gem is at the foundation of <code>action_mailer</code>, and doing
so reduced the chances of having emails validated by ActiveValidators and
rejected by <code>action_mailer</code> or MTAs.</p>

<p>The EmailValidator can validate emails in the form <code>user@domain.tld</code>,
but <code>mail</code> accepts any RFC-valid email address (1), like <code>"User" &lt;user@domain.tld&gt;</code>.
Although that kind of format is correct, most apps want to only keep the <code>user@domain.tld</code> part
and leave the rest.</p>

<p>Since <a href="https://github.com/cesario/activevalidators/commit/d77d9105e5831bfac16cadbeaf9dc055d5e941ff">this commit</a>, the email validator now accepts an option
to constraint a bit more the email validation:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">validates</span> <span class="ss">:field_to_validate</span><span class="p">,</span> <span class="ss">:email</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="ss">:strict</span> <span class="o">=&gt;</span> <span class="kp">true</span><span class="o">/</span><span class="kp">false</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>By default, <code>strict</code> is set to <code>false</code> and the <code>mail</code> gem validation will apply.
When <code>strict</code> is set to <code>true</code>, only emails in the form <code>user@domain.tld</code> will be valid.</p>

<p>I&#8217;m wondering it would make sense to switch the default to <code>true</code> (I tend to prefer sensible defaults).
Don&#8217;t hesitate to give an opinion on that and thanks for using ActiveValidators.</p>

<ol>
<li><a href="http://tools.ietf.org/html/rfc5321">RFC 5321</a>, <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> and <a href="http://tools.ietf.org/html/rfc3696">RFC 5396</a>.</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[What is the best way to pass NSManagedObjectContext around in iOS applications?]]></title>
    <link href="http://franck.verrot.fr/blog/2012/01/18/best-way-to-pass-nsmanagedobjectcontext-around-in-ios-applications/"/>
    <updated>2012-01-18T00:09:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2012/01/18/best-way-to-pass-nsmanagedobjectcontext-around-in-ios-applications</id>
    <content type="html"><![CDATA[<p><strong>TL;DR</strong>
Passing an <code>NSManagedObjectContext</code> in each and every <code>NSViewController</code> that
needs CoreData can be done by different means, but some are frowned upon. In doubt, inject it.</p>

<p>While pair-reviewing some code with my colleague <a href="http://www.vtourraine.net/blog/">Vincent Tourraine</a>,
we realized we wrote this kind of code into each <code>viewDidLoad:</code> method of each <code>NSViewController</code> subclasses we created:</p>

<figure class='code'><figcaption><span>Please don&#8217;t use this snippet in your project - bad.m </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="n">managedObjectContext</span> <span class="o">=</span> <span class="p">[[[</span><span class="n">UIApplication</span> <span class="n">sharedApplication</span><span class="p">]</span> <span class="n">delegate</span><span class="p">]</span> <span class="n">managedObjectContext</span><span class="p">];</span>
</span></code></pre></td></tr></table></div></figure>


<p>Doing so is more or less the same as using a global variable, as calling <code>sharedApplication</code> on <code>UIApplication</code> returns the singleton
application instance. I kind of felt this was a code smell so I investigated.</p>

<p>After a couple of minute of browsing Apple&#8217;s documentation, here&#8217;s what <a href="http://developer.apple.com/library/ios/#DOCUMENTATION/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html#//apple_ref/doc/uid/TP40008283-SW2">we can read</a></p>

<blockquote><p>A view controller typically **shouldn’t retrieve** the context from a global object<br/>such as the application delegate. This tends to make the application<br/>architecture rigid. [&#8230;]<br/>[&#8230;]<br/>When you create a view controller, you pass it a context. [&#8230;]</p></blockquote>


<p>If you use the good old <code>nib|xib</code>s (I&#8217;m acting as if I was confident with them) and
instantiate your controllers programmatically, this sounds dead easy, but what
if you use the brand new shiny <code>Storyboard</code>s?</p>

<p>The only solution I came up with, that will comply with Apple&#8217;s recommendation, is to use <code>prepareForSegue</code>, like this:</p>

<figure class='code'><figcaption><span>If you trust me enough, use this code :) - better.m </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="cp">#import &quot;MyMainController.h&quot;</span>
</span><span class='line'><span class="cp">#import &quot;MyOtherController.h&quot;</span>
</span><span class='line'><span class="k">@implementation</span> <span class="nc">MyMainController</span>
</span><span class='line'><span class="o">-</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nl">prepareForSegue:</span><span class="p">(</span><span class="n">UIStoryboardSegue</span> <span class="o">*</span><span class="p">)</span><span class="n">segue</span> <span class="nl">sender:</span><span class="p">(</span><span class="kt">id</span><span class="p">)</span><span class="n">sender</span> <span class="p">{</span>
</span><span class='line'>    <span class="k">if</span><span class="p">([[</span><span class="n">segue</span> <span class="n">identifier</span><span class="p">]</span> <span class="nl">isEqualToString:</span><span class="s">@&quot;SegueToMyOtherController&quot;</span><span class="p">])</span> <span class="p">{</span>
</span><span class='line'>        <span class="n">MyOtherController</span> <span class="o">*</span><span class="n">controller</span> <span class="o">=</span> <span class="p">[</span><span class="n">segue</span> <span class="n">destinationViewController</span><span class="p">];</span>
</span><span class='line'>        <span class="n">controller</span><span class="p">.</span><span class="n">managedObjectContext</span> <span class="o">=</span> <span class="n">managedObjectContext</span><span class="p">;</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<p>If your main controller doesn&#8217;t have any <code>NSManagedObjectContext</code>, you might
want to inject it from within the method
<code>application:didFinishLaunchingWithOptions:</code> of your AppDelegate, as you can see if you create a new CoreData project from the templates.</p>

<p>So next time, no more abuse of the <code>sharedApplication</code> !</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ActiveValidators 1.3.0]]></title>
    <link href="http://franck.verrot.fr/blog/2011/03/20/activevalidators-130/"/>
    <updated>2011-03-20T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2011/03/20/activevalidators-130</id>
    <content type="html"><![CDATA[<p>ActiveValidators 1.3.0 has been released!</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">gem</span> <span class="n">install</span> <span class="n">activevalidators</span>
</span></code></pre></td></tr></table></div></figure>


<p>Read on for the full changelog.</p>

<!--more-->


<h2>Features:</h2>

<ul>
<li>Thanks to Renato, the phone validator now supports multiple countries.</li>
<li><a href="https://github.com/codegram/date_validator">date_validator</a> 0.6.1</li>
</ul>


<h2>Fixes:</h2>

<ul>
<li>Some misleading info in the README</li>
<li>1.9 compatibility in the test suite</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Find out where a Rake task is defined]]></title>
    <link href="http://franck.verrot.fr/blog/2011/02/20/find-out-where-a-rake-task-is-defined/"/>
    <updated>2011-02-20T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2011/02/20/find-out-where-a-rake-task-is-defined</id>
    <content type="html"><![CDATA[<p><em>TL;DR</em>
Rake > 0.8.7 has a handy <code>Rake::Task#locations</code> method that makes it
damn easy to know where a task is defined or enhanced.</p>

<p>During the last <a href="http://lyonrb.fr">LyonRb</a> meetup we read a quite large
portion of Rake&#8217;s source code. The idea was to find an easy way to determine
what file was defining/enhancing what task.</p>

<p><a href="http://twitter.com/richarkmichael">Richard</a> and I just opened Rake
0.8.7&#8217;s source code (from our local machine&#8217;s RVM directory) and started hacking a bit to have that feature&#8230;</p>

<!--more-->


<p>Two days after I can tell you that you won&#8217;t need to hack anything
because it&#8217;s actually already implemented in Rake&#8217;s master since <a href="https://rubygems.org/gems/rake">May 19th
2009 by Jim Weirich</a>.</p>

<p>It wasn&#8217;t obvious to us as <a href="https://rubygems.org/gems/rake">Rake 0.8.7</a>
has been released on&#8230; May 15th 2009!</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>~  cd /tmp && git clone git://github.com/jimweirich/rake.git && cd rake && rake gem && gem install pkg/rake-0.8.99.5.gem
</span><span class='line'>Cloning into rake...
</span><span class='line'>remote: Counting objects: 5804, done.
</span><span class='line'>remote: Compressing objects: 100% (2489/2489), done.
</span><span class='line'>remote: Total 5804 (delta 3387), reused 5519 (delta 3180)
</span><span class='line'>Receiving objects: 100% (5804/5804), 1.23 MiB | 613 KiB/s, done.
</span><span class='line'>Resolving deltas: 100% (3387/3387), done.
</span><span class='line'>RCov is not available
</span><span class='line'>ERROR: unknown action 'gemsets'
</span><span class='line'>Successfully installed rake-0.8.99.5
</span><span class='line'>1 gem installed
</span><span class='line'>
</span><span class='line'>/tmp  cat &gt;&gt; foo.rb &lt;&lt; EOF
</span><span class='line'>heredoc&gt; desc 'foo'
</span><span class='line'>heredoc&gt; task :foo do; end
</span><span class='line'>heredoc&gt; desc 'foobar'
</span><span class='line'>heredoc&gt; task :foobar do; end
</span><span class='line'>heredoc&gt; EOF
</span><span class='line'>
</span><span class='line'>/tmp  cat &gt;&gt; baz.rb &lt;&lt; EOF
</span><span class='line'>heredoc&gt; desc 'baz'
</span><span class='line'>heredoc&gt; task :baz do; end
</span><span class='line'>heredoc&gt; task 'foobaz'
</span><span class='line'>heredoc&gt; task :foobar do; end
</span><span class='line'>heredoc&gt; EOF
</span><span class='line'>
</span><span class='line'>/tmp  cat &gt;&gt; Rakefile &lt;&lt; EOF
</span><span class='line'>heredoc&gt; load 'foo.rb'
</span><span class='line'>heredoc&gt; load 'baz.rb'
</span><span class='line'>heredoc&gt; EOF
</span><span class='line'>
</span><span class='line'>/tmp  rake -T
</span><span class='line'>rake baz      # baz
</span><span class='line'>rake foo      # foo
</span><span class='line'>rake foobar   # foobar
</span><span class='line'>
</span><span class='line'>/tmp  rake --where
</span><span class='line'>rake baz                            baz.rb:2:in `&lt;top (required)&gt;'
</span><span class='line'>rake foo                            foo.rb:2:in `&lt;top (required)&gt;'
</span><span class='line'>rake foobar                         foo.rb:4:in `&lt;top (required)&gt;'
</span><span class='line'>rake foobar                         baz.rb:4:in `&lt;top (required)&gt;'</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LyonRb Bilan de l'apéro Ruby Lyon du 19 février 2011]]></title>
    <link href="http://franck.verrot.fr/blog/2011/02/19/bilan-de-l-apero-ruby-lyon-du-17-fevrier-2011/"/>
    <updated>2011-02-19T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2011/02/19/bilan-de-l-apero-ruby-lyon-du-17-fevrier-2011</id>
    <content type="html"><![CDATA[<p>Que de monde pour ce nouvel apéro Ruby à Lyon. L&#8217;élément encourageant
étant que le groupe ne descend plus en dessous de la douzaine!</p>

<p>Quatre nouvelles têtes: <a href="https://github.com/TiteiKo">Marion</a>, Michel,
<a href="http://vzmind.tumblr.com/">Vincent</a> et <a href="http://twitter.com/#!/richardkmichael/">Richard</a>.
Bienvenue à vous!</p>

<p>Les discussions se sont rapidement orientées sur le <a href="http://lyon.startupweekend.org">StartUp Weekend Lyon</a>,
où Vincent, JM, Pierre-Alexandre et Frédéric ont eu pour mission de faire un peu se prosélytisme :)</p>

<p>Côté technique, nous avons eu un peu de temps pour:</p>

<ul>
<li>Disséquer Rake afin de trouver un moyen simple pour retrouver où une
tâche est définie</li>
<li>Discuter RESTful API et l&#8217;utilisation de l&#8217;entête Accept pour
effectuer le versioning.</li>
<li>Philosopher sur les frameworks MVC comme ASP.NET MVC (beaucoup de
respect pour Scott Guthrie et le travail de son équipe), Symfony.</li>
</ul>


<p>Je n&#8217;ai pas réussi à parler de Seaside (Smalltalk)&#8230; je ne désespère
pas!</p>

<p>Le livre <a href="http://www.amazon.com/Rails-Way-Addison-Wesley-Professional-Ruby/dp/0321601661">&#8220;The Rails 3 Way&#8221;</a> a été gagné par Camille par tirage au sort.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LyonRb Bilan apero Ruby du 2 decembre 2010]]></title>
    <link href="http://franck.verrot.fr/blog/2010/12/03/lyonrb-bilan-apero-ruby-du-2-decembre-2010/"/>
    <updated>2010-12-03T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/12/03/lyonrb-bilan-apero-ruby-du-2-decembre-2010</id>
    <content type="html"><![CDATA[<p>Encore de nouvelles têtes!</p>

<!--more-->


<ul>
<li><a href="http://www.anthonymarechal.com/">Anthony Maréchal</a> et <a href="http://www.benoitmarechal.com/">Benoît Maréchal</a>, fondateurs de <a href="http://www.waluutwins.com">WaluuTwins</a></li>
<li><a href="http://twitter.com/iUser69/">Cédric Fabianski</a>, développeur Ruby et Rails chez <a href="http://www.certilience.fr">Certilience</a></li>
</ul>


<p>Mais également <a href="https://github.com/luckynumberslevin">Laurent</a>, <a href="http://guillaume-barillot.com">Guillaume</a>, <a href="http://dmathieu.com">Damien</a>, <a href="http://cappert.com">Camille</a> et une autre personne dont je ne me souviens plus du nom mais qui travaille chez <a href="http://www.lim.eu">LIM SAS</a>.</p>

<p>Discussions intéressantes autour de:</p>

<ul>
<li>Capistrano</li>
<li>Git</li>
<li>Diaspora</li>
<li>Metaprogramming Ruby</li>
<li>Eager/lazy loading des associations dans Rails</li>
<li>Projets pro de chacun</li>
<li>etc&#8230;</li>
</ul>


<p>Je n&#8217;ai pas pu faire mon lightening talk sur une des expérimentations que je suis en train de faire, ce sera pour la prochaine fois!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[No Querying Views]]></title>
    <link href="http://franck.verrot.fr/blog/2010/11/28/no-querying-views/"/>
    <updated>2010-11-28T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/11/28/no-querying-views</id>
    <content type="html"><![CDATA[<p>I made this plugin when we migrated to Rails 3. It basically prevents the development team from triggering any database query from the views.</p>

<!--more-->


<p><strong>TL;DR</strong>
Make sure you understand the data you need in your views, because manipulating directly ActiveRecord objects in your view is both powerful (follow associations, use model methods, etc.) and dangerous (N+1 problem). (and yes, this is a copy of the <a href="http://www.verrot.fr/archives/2010/11/27/lyonrb-bilan-de-la-dernire-rencontre/">No Querying Views</a> README because the blog was not broken at the time I published it)</p>

<p>This Rails3 plugin will tell you when you and your folks are querying the
database from something else than a controller and a model.</p>

<p>It supports SQLite, SQLite3, MySQL, PostgreSQL and Mongoid.</p>

<h2>Context</h2>

<p>Rails is a MVC framework. The separation of concern should be respected
to prevent bad things to happen in your application.</p>

<p>Example: An order has N order lines. Each of these order lines has 1
related item, and each of these items belongs to 1 category.</p>

<p>In Ruby code, your models would look like this:</p>

<h5>app/models/order.rb</h5>

<pre><code>class Order &lt; ActiveRecord::Base
  has_many :lines
end
</code></pre>

<h5>app/models/line.rb</h5>

<pre><code>class Line &lt; ActiveRecord::Base
  has_one :item
end
</code></pre>

<h5>app/models/item.rb</h5>

<pre><code>class Item &lt; ActiveRecord::Base
  belongs_to :category
end
</code></pre>

<h5>app/models/category.rb</h5>

<pre><code>class Category &lt; ActiveRecord::Base
end
</code></pre>

<p>Now, if you want to display them on a single page, here is a naive version of
order_controller.rb:</p>

<h5>app/controllers/order_controller.rb</h5>

<pre><code>class OrderController &lt; ApplicationController
  def show
    @order = Order.find(params[:id])  # 1 query
  end
end
</code></pre>

<p>And a naive version of the views used to display the result:</p>

<h5>app/views/orders/show.html.haml</h5>

<pre><code>%h1
  = @order.title
%h2
  %span Items
  %ul
    = render :partial =&gt; 'lines', :collection =&gt; order.lines   # 1 query, so far: 2 queries
</code></pre>

<h5>app/views/orders/_lines.html.haml executed for <strong>each single line</strong></h5>

<pre><code>%li
  %span
    = line.item.title          # 1 query
    = line.price
  %div{:class =&gt; 'item_description'}
    = line.item.description    # 0 query (cached)
    = line.item.category       # 1 query
</code></pre>

<h2>The problem</h2>

<p>If you use a tool that generates execution traces (like NewRelic RPM),
you will see that - for 1 order, 40 lines, 30 items, 20 categories - you will
execute:
   1 (select * from order)
+  1 (select * from lines inner join &#8230; where order_id = foo)
+ 40 (select * from items inner join &#8230; where line.item_id = bar)
+ 40 (select * from categories inner join &#8230; where item.category_id = baz)</p>

<hr />

<p>  82 queries against the database!</p>

<p>This is called the <a href="http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations">N + 1 problem</a> and it can be solved by an eager-loading strategy.</p>

<h6>## OH: &#8220;Yeah, but my database is so small and so fast that I don&#8217;t even see that!&#8221;</h6>

<p>This is true if you are the only user of the website.  But Rails will also have
troubles generating the page (HAML, ERB, whatever) and NewRelic won&#8217;t tell you
that the queries are slowing down the application: the queries are fast as
hell.</p>

<p>The combination of the rendering and the querying is slowing down the application, because:</p>

<ol>
<li>Rendering a partial is slower than inline code</li>
<li>Executing a query costs time (retrieving the DB connection within
the pool, executing and fetching the results, &#8230;): the resources
are not being used for free on your machine.</li>
</ol>


<h2>The solution</h2>

<p>Silver bullets don&#8217;t exist, but most of the time you can speed up the
performance by eager-loading the data you expect in your views.</p>

<p>From an architectural point of view, it is <strong>wrong</strong> to query the DB
from a view. There are many reasons not to do so and the internet is
full of literature about it.</p>

<p>Right now, here is a piece of code to help you remove any DB query from your
views.</p>

<h2>What does this code do?</h2>

<p>It will raise an exception everytime you and your people try to query the
database from within a view.</p>

<p>It only overrides the <code>execute</code> method of the adapter and checks the
call stack.</p>

<h3>Rails 3.x</h3>

<h4>ActiveRecord</h4>

<h5>Install</h5>

<pre><code>cd /my/rails/3/app_root/
wget http://github.com/cesario/no_querying_views/raw/master/no_querying_views.rb &gt; config/initializers/no_querying_views.rb
</code></pre>

<h5>Uninstall</h5>

<pre><code>cd /my/rails/3/app_root/
rm config/initializers/no_querying_views.rb
</code></pre>

<h4>Mongoid</h4>

<h5>Install</h5>

<pre><code>cd /my/rails/3/app_root/
wget http://github.com/cesario/no_querying_views/raw/master/mongoid_no_querying_views.rb &gt; config/initializers/mongoid_no_querying_views.rb
</code></pre>

<h5>Uninstall</h5>

<pre><code>cd /my/rails/3/app_root/
rm config/initializers/no_querying_views.rb
</code></pre>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LyonRb Bilan de la dernière rencontre]]></title>
    <link href="http://franck.verrot.fr/blog/2010/11/27/lyonrb-bilan-de-la-derniere-rencontre/"/>
    <updated>2010-11-27T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/11/27/lyonrb-bilan-de-la-derniere-rencontre</id>
    <content type="html"><![CDATA[<p>Bien que cela fasse plus d&#8217;un mois que la dernière rencontre des &#8220;Rubyistes&#8221; Lyonnais (disons Rhône-Alpins) ait eu lieu, je ne trouve que maintenant (à moins d&#8217;une semaine du prochain apéro) le temps de le commenter&#8230;</p>

<p>Je pense qu&#8217;il s&#8217;agit du premier apéro qui réunit tant de personnes. Nous étions une bonne douzaine (14?), dont <a href="http://pcreux.com/">Philippe</a> de retour du Canada, <a href="http://guillaume-barillot.com/blog/fr/33--blog">Guillaume</a> et bien d&#8217;autres curieux qui rejoignent nos rangs.</p>

<p>Philippe a pu présenter <a href="https://github.com/gregbell/active_admin">ActiveAdmin</a>, un projet assez intéressant qui permet de monter des interfaces d&#8217;administrations assez facilement, et qui fournit une DSL assez bien pensée.</p>

<p>Pierre-Alexandre a enfin pu présenter son clavier basé sur la disposition BEPO. Amis assujettis aux troubles musculosquelettiques&#8230;</p>

<p>J&#8217;ai pu converser avec une autre personne, venant elle du monde Python, qui a pour but d&#8217;ouvrir le code de son ORM (toujours écrit en Python) d&#8217;ici la fin d&#8217;année. Projet très prometteur.</p>

<p>Cet apéro a surtout pu parler de Rails 3 et des nouveautés de cette version, du nouveau routeur à Arel. La faible adoption de cette dernière version est dûe à la compatibilité encore faible des plugins/librairies existantes avec Rails 3 (et Ruby 1.9.2).</p>

<p>Prochaine édition ce 2 décembre. Toutes les informations pour s&#8217;y rendre: <a href="http://lyonrb.fr">ici!</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New blog engine]]></title>
    <link href="http://franck.verrot.fr/blog/2010/11/08/new-blog-engine/"/>
    <updated>2010-11-08T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/11/08/new-blog-engine</id>
    <content type="html"><![CDATA[<p>Trying out a new blog engine.</p>

<p>Pretty simple backend: everything is stored on Github so publicly
accessible.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[RubyCampLyon 2010 wrapping up]]></title>
    <link href="http://franck.verrot.fr/blog/2010/04/17/rubycamplyon-2010-wrapping-up/"/>
    <updated>2010-04-17T00:00:00+02:00</updated>
    <id>http://franck.verrot.fr/blog/2010/04/17/rubycamplyon-2010-wrapping-up</id>
    <content type="html"><![CDATA[<p>The RubyCamp Lyon 2010 took place yesterday, Saturday 17th. I was great meeting all those people interested in Ruby, for both professional and amateur matters. Eyrolles was sponsoring the event and offered 10 books (I didn&#8217;t win one though - that&#8217;s for the sucking part :)).</p>

<p>I also obtained a last-minute sponsoring from Engine Yard, but as I obtained the required info the night before the presentation, I only showed a little bit the interface but didn&#8217;t do anything real with it. Instead, I used Heroku and presented the 60-second deployment stuff. I think I made my point there: configuring servers and low-level stuff isn&#8217;t fun anymore, let&#8217;s put the application at the center of all.</p>

<p>So here&#8217;s my slides. Be kind with the layout and content, it was best seeing me (or anybody else talking :)) live than it&#8217;s gonna be reading it.</p>

<div style="width:425px" id="__ss_3768207"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/CesarioGW/ruby-in-the-clouds-3768207" title="Ruby in the Clouds">Ruby in the Clouds</a></strong><object width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=ruby-in-the-clouds2311&stripped_title=ruby-in-the-clouds-3768207" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=ruby-in-the-clouds2311&stripped_title=ruby-in-the-clouds-3768207" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/CesarioGW">Franck Verrot</a>.</div></div>


<p>I haven&#8217;t had time to go thru the other presentation I prepared called &#8220;Ruby Software Architecture&#8221;, but I&#8217;ll do that during another event.</p>

<p>Anyhoo&#8230; I&#8217;m looking forward to the next &#8220;Apéro Ruby&#8221; now that the group is in motion!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rails 3, Railties and Engines]]></title>
    <link href="http://franck.verrot.fr/blog/2010/04/07/rails-3-railties-and-engines/"/>
    <updated>2010-04-07T00:00:00+02:00</updated>
    <id>http://franck.verrot.fr/blog/2010/04/07/rails-3-railties-and-engines</id>
    <content type="html"><![CDATA[<p>Rails 3 brings a lot of useful features. The main one, in my humble opinion, is the introduction of the classes Rails::Railtie and Rails::Engine.</p>

<p>They bring the modularity that made code more reusable and easily integrable in your current code base. They also prove that there no reason to say that Rails is not ready for the Enterprise. One quick tip for the party poopers (you know who you are ;)): <a href=":http://jruby.org/">JRuby</a> makes things even easier for your development operations team members as it allows you to run your Ruby app (ie: Rails) within your favorite App Server (Websphere, Tomcat, you name them).</p>

<p>In this article, I will try to explain a little bit what are these new classes, how they were implemented and how to start using them.</p>

<p>If you want to see a live presentation of this, come and join us to the <a href="http://www.rubyfrance.org/association/groupes/lyon/">RubyCamp Lyon 2010</a> on April 17th.</p>

<h2>The history:  Merb + Rails = Rails 3</h2>

<p>If you&#8217;re reading the gurus&#8217; blogs, you may already know that Rails have had a major <a href="http://www.engineyard.com/blog/2009/6-steps-to-refactoring-rails-for-mere-mortals/">refactoring</a> and <a href="http://yehudakatz.com/2009/07/19/rails-3-the-great-decoupling/">decoupling</a> phase done by the Rails Core Team (Yehuda Katz being the one doing the communication about it).</p>

<p>This gave birth to an AbstractController class, that reduced the tight-coupling between ActionController and ActionView, and lots of other cool stuff. But the real change comes down to the addition of the Railtie class. If you want to know more about how Rails 3 layers fit one onto another, I suggest your read <a href="http://omgbloglol.com/post/344792822/the-path-to-rails-3-introduction">Jeremy McAnally&#8217;s post &#8220;The Path to Rails 3 : Introduction&#8221;</a></p>

<h2>Introducing Railties and Engines</h2>

<p><small>Note: To clear any future confusion, we can safely state that an Engine is a Railtie (line 89 of <em>rails3_beta_gem/lib/rails/engines.rb</em> : <strong>class Engine &lt; Railtie</strong>).</small></p>

<p>The major components of Rails, from Action View to Active Record thru Action Mailer and others, have their own Railtie inherited from Rails::Railtie. Each Railtie has its own initializers being triggered by the overall Rails boot process, its own generators, tasks, &#8230; It&#8217;s then up to the Rails::Application object to coordinate the boot process and sequentially ask each Railtie to initialize itself. De facto, this removes the tight coupling that we used to see in the previous versions of Rails.</p>

<p>A Rails::Application is also a Railtie, but a bit more: an Engine. An Engine is an extension (a derived class) of the Railtie class. <strong>Please do not think about Rails 3 Railtie as the old Rails 2.x engines plugin!</strong> Rails 3 Engines are core aspects of Rails. The noticeable difference between a Railtie and an Engine (as far as I investigated) is that an Engine:</p>

<ul>
<li>comes with a predefined set of initializers (locales, metals, view paths, etc.)</li>
<li>has its own <em>load_paths</em>, <em>eager_load_paths</em> and <em>load_once_paths</em> (scoped to the current Engine)</li>
</ul>


<p>Engines make it easy for anyone to modify or extend, à la Merb, any part of a Rails application out of the box - from the ORM to the rendering system -  and for instance drop Active Record in favor of DataMapper or add an authentication system (like <a href="http://github.com/plataformatec/devise">Devise</a>).</p>

<h2>Let&#8217;s understand how it all works</h2>

<p>Each Rails 3 Application has now a file called <em>config/application.rb</em>, that defines <strong>MyAppName::Application</strong>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="s1">&#39;../boot&#39;</span><span class="p">,</span> <span class="bp">__FILE__</span><span class="p">)</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;rails/all&#39;</span>
</span><span class='line'><span class="no">Bundler</span><span class="o">.</span><span class="n">require</span><span class="p">(</span><span class="ss">:default</span><span class="p">,</span> <span class="no">Rails</span><span class="o">.</span><span class="n">env</span><span class="p">)</span> <span class="k">if</span> <span class="n">defined?</span><span class="p">(</span><span class="no">Bundler</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">module</span> <span class="nn">MyAppName</span>
</span><span class='line'>    <span class="k">class</span> <span class="nc">Application</span> <span class="o">&lt;</span> <span class="no">Rails</span><span class="o">::</span><span class="no">Application</span>
</span><span class='line'>        <span class="o">.</span><span class="n">.</span><span class="o">.</span><span class="n">.</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>You can only have one instance of a <strong>Rails::Application</strong> at a time, it&#8217;s a singleton and it will always point to <strong>MyAppName::Application.instance</strong>. If we now have a look at the code that defines <strong>Rails::Application</strong>, we can see this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;rails/plugin&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;rails/engine&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Application</span> <span class="o">&lt;</span> <span class="no">Engine</span>
</span><span class='line'>    <span class="nb">autoload</span> <span class="ss">:Bootstrap</span><span class="p">,</span>      <span class="s1">&#39;rails/application/bootstrap&#39;</span>
</span><span class='line'>    <span class="nb">autoload</span> <span class="ss">:Configurable</span><span class="p">,</span>   <span class="s1">&#39;rails/application/configurable&#39;</span>
</span><span class='line'>    <span class="nb">autoload</span> <span class="ss">:Configuration</span><span class="p">,</span>  <span class="s1">&#39;rails/application/configuration&#39;</span>
</span><span class='line'>    <span class="nb">autoload</span> <span class="ss">:Finisher</span><span class="p">,</span>       <span class="s1">&#39;rails/application/finisher&#39;</span>
</span><span class='line'>    <span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="n">snip</span> <span class="o">.</span><span class="n">.</span><span class="o">.</span><span class="n">.</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">initialize!</span>
</span><span class='line'>        <span class="n">run_initializers</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span>
</span><span class='line'>        <span class="nb">self</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="n">snip</span> <span class="o">.</span><span class="n">.</span><span class="o">.</span><span class="n">.</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">initializers</span>
</span><span class='line'>        <span class="n">initializers</span> <span class="o">=</span> <span class="no">Bootstrap</span><span class="o">.</span><span class="n">initializers_for</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span>
</span><span class='line'>        <span class="n">railties</span><span class="o">.</span><span class="n">all</span> <span class="p">{</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span> <span class="n">initializers</span> <span class="o">+=</span> <span class="n">r</span><span class="o">.</span><span class="n">initializers</span> <span class="p">}</span>
</span><span class='line'>        <span class="n">initializers</span> <span class="o">+=</span> <span class="k">super</span>
</span><span class='line'>        <span class="n">initializers</span> <span class="o">+=</span> <span class="no">Finisher</span><span class="o">.</span><span class="n">initializers_for</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span>
</span><span class='line'>        <span class="n">initializers</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="n">snip</span> <span class="o">.</span><span class="n">.</span><span class="o">.</span><span class="n">.</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Interesting! If you have a look at the <strong>Rails::Application::Bootstrap</strong> and <strong>Rails::Application::Finisher</strong> modules, they are including another module: <strong>Rails::Initializable</strong>, which is defining the <strong>Initializer</strong> class, finally defining the <strong>run_initalizers</strong> method we can see above.</p>

<p>So what does that mean at the end? Each of your Engine and Railtie will be able to hook into the boot process, right before the other initializers or right after. From the user (aka developer) perspective, it&#8217;s easy to use:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">MyModule</span>
</span><span class='line'>    <span class="k">class</span> <span class="nc">Railtie</span> <span class="o">&lt;</span> <span class="no">Rails</span><span class="o">::</span><span class="no">Railtie</span>
</span><span class='line'>        <span class="c1"># initialize before</span>
</span><span class='line'>        <span class="n">initializer</span> <span class="s2">&quot;my_module.initialize_my_thingy&quot;</span><span class="p">,</span> <span class="ss">:before</span> <span class="o">=&gt;</span> <span class="s2">&quot;some_other_railtie.initialize_its_thingy&quot;</span> <span class="k">do</span>
</span><span class='line'>        <span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="n">some</span> <span class="n">code</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>        <span class="c1"># initialize after</span>
</span><span class='line'>        <span class="n">initializer</span> <span class="s2">&quot;my_module.initialize_my_other_thingy&quot;</span><span class="p">,</span> <span class="ss">:after</span> <span class="o">=&gt;</span> <span class="s2">&quot;some_other_railtie.initialize_its_other_thingy&quot;</span> <span class="k">do</span>
</span><span class='line'>        <span class="o">.</span><span class="n">.</span><span class="o">.</span> <span class="n">some</span> <span class="n">code</span>
</span><span class='line'>        <span class="k">end</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Creating an Engine</h3>

<p>If you want your engine to work within your application, you obviously have to put in the load path of it. You can do this by putting it your code just like you would do for a plugin: in your <em>vendor/plugins</em> directory. The basic structure looks like:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># vendor/plugins/my_gem/lib/engine.rb</span>
</span><span class='line'><span class="k">module</span> <span class="nn">MyEngine</span>
</span><span class='line'>  <span class="k">class</span> <span class="nc">Engine</span> <span class="o">&lt;</span> <span class="no">Rails</span><span class="o">::</span><span class="no">Engine</span>
</span><span class='line'>    <span class="n">engine_name</span> <span class="ss">:my_engine</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>To use it in your Rails application, just update your <em>Gemfile</em> and simply put:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'>  <span class="n">gem</span> <span class="s2">&quot;my_gem&quot;</span><span class="p">,</span> <span class="ss">:require</span> <span class="o">=&gt;</span> <span class="s2">&quot;my_engine&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>By putting it in your Gemfile, and your Gemfile being used during the startup of your applicaiton, the initializers of your engine will automatically run, settings up the routes, loading the models, controllers, tasks, translations&#8230; that you may have defined in your Engine. Available paths are all pointing to a Rails-style folder name from the root folder of your engine (ie: <em>paths.app.views</em> will point to <em>app/views</em>):</p>

<ul>
<li>app.[controllers, helpers, models, metals, views, observers, &#8230;]</li>
<li>lib</li>
<li>lib.tasks</li>
<li>config.[initializers, locales, routes]</li>
</ul>


<h2>To be continued&#8230;</h2>

<p>You will find on <a href="http://www.themodestrubyist.com/">The Modest Rubyist</a> very neat tutorials on how to create your Engine from the ground up.</p>

<p>I will continue with a new article that will be the base of the talk I will give during the <a href="http://www.rubyfrance.org/association/groupes/lyon/">RubyCamp Lyon 2010</a> about enterprise Ruby-based software architecture.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Live-Note got its own Google Chrome Extension]]></title>
    <link href="http://franck.verrot.fr/blog/2010/03/25/live-note-got-its-own-google-chrome-extension/"/>
    <updated>2010-03-25T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/03/25/live-note-got-its-own-google-chrome-extension</id>
    <content type="html"><![CDATA[<p>Thanks to <a href="http://www.google.com/profiles/luciano.santabrigida#buzz">Luciano (@lucianosb)</a> Live-Note has got its own Google Chrome Extension.</p>

<p>He even shot a video about it:</p>

<!--more-->




<object width="560" height="340"><param name="movie" value="http://www.youtube.com/v/1fs730GJD_U&hl=fr_FR&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/1fs730GJD_U&hl=fr_FR&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"></embed></object>


<p>So I guess it&#8217;s time for me to make Live-Note a real product by setting up a couple of tools like an issue tracker and a wiki (for the documentation).</p>

<p>Few figures I&#8217;m kinda proud of. Live-Note is today:</p>

<ul>
<li>42 users</li>
<li>3700+ notes added to Google Wave. These waves/blips are completely yours, only you (and the robot) have access to it, so it&#8217;s entirely private.</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Fatal GCJ GNU Compiler for Java is not supported by JRuby]]></title>
    <link href="http://franck.verrot.fr/blog/2010/03/22/fatal-gcj-gnu-compiler-for-java-is-not-supported-by-jruby/"/>
    <updated>2010-03-22T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/03/22/fatal-gcj-gnu-compiler-for-java-is-not-supported-by-jruby</id>
    <content type="html"><![CDATA[<p>If you ever encountered this when installing JRuby on Ubuntu:</p>

<p><code>Fatal: GCJ (GNU Compiler for Java) is not supported by JRuby.</code></p>

<p>Doing</p>

<p><code>export JAVA_HOME=/usr/lib/jvm/java-6-sun/jre</code></p>

<p>could do the trick, given you&#8217;ve installed sun-java6&#8217;s packages on your machine.</p>

<p>I hope it&#8217;ll help.</p>

<!--more-->


<p>If you ever encountered this when installing JRuby on Ubuntu:</p>

<p><code>Fatal: GCJ (GNU Compiler for Java) is not supported by JRuby.</code></p>

<p>Doing</p>

<p><code>export JAVA_HOME=/usr/lib/jvm/java-6-sun/jre</code></p>

<p>could do the trick, given you&#8217;ve installed sun-java6&#8217;s packages on your machine.
I hope it&#8217;ll help.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Git Fast Forward Merges]]></title>
    <link href="http://franck.verrot.fr/blog/2010/03/11/git-fast-forward-merges/"/>
    <updated>2010-03-11T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/03/11/git-fast-forward-merges</id>
    <content type="html"><![CDATA[<p>Moving our current projects codebase from Subversion to Git was a nice move. This plus the adoption of the feature-centric way of developing (BDD + Scrum + Kanban) and our repositories are now cleared of any form of waste (useless LOC written &#8220;just in case&#8221;). Now, we must adapt the usage we have of Git and one that we just initiated is the non fast forward merge.</p>

<p>Moving our current projects codebase from Subversion to Git was a nice move. This plus the adoption of the feature-centric way of developing (BDD + Scrum + Kanban) and our repositories are now cleared of any form of waste (useless LOC written &#8220;just in case&#8221;).</p>

<p>Now, we must adapt the usage we have of Git and one that we just initiated is the non fast forward merge.</p>

<p>Cheap branches with Git are great and it&#8217;s a pleasure to work with them for both new implementations and quick experimentations. Behavior-Driven Development and agile methodologies don&#8217;t have to prove they work anymore: it&#8217;s just our only way of working now (which is IMHO good, not because I am responsible for its adoption, but because it actually <em>works</em>).</p>

<p>Being a small company we don&#8217;t have so many branches, except master (for the continuously integrated trunk) and few tags (for deployed or &#8220;soon-deployed-yet-to-be-optimized&#8221; versions). But it&#8217;s quite simple to dive into the workflow, fork any branch and merge it back when done (&#8220;done&#8221; meaning: tests are still turning green).
For a longer feature, if breaking the implementation in smaller tasks wasn&#8217;t possible, it&#8217;s easy to merge often the master to the feature&#8217;s branch to avoid the big bang integration resulting from a branch too long away from its parent.</p>

<p>In one of our projects, we wanted to experiment two different ways of coding the same feature. Easy to do, easy to figure out what branch to keep and merge to the master branch. Having low activity on our codebase, Git merges are fast-forward merges.</p>

<p>From the Git documentation:</p>

<h4>Fast-forward merges</h4>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>[...] Normally, a merge results in a merge commit, with two parents, one pointing at each of the two lines of development that were merged.</span></code></pre></td></tr></table></div></figure>


<p>However, if the current branch is a descendant of the other—so every commit present in the one is already contained in the other—then git just performs a &#8220;fast-forward&#8221;; the head of the current branch is moved forward to point at the head of the merged-in branch, without any new commits being created.</p>

<p>So when we merged back, Git just doesn&#8217;t care about the branch we created and pretend that it never existed and so we can&#8217;t see anywhere in the log we entered &#8220;git merge&#8221;. At that time, <em>working on master would have had the exact same effect</em>. If we ask to ourselves &#8220;did we create a branch for that?&#8221; a couple of weeks after the development, we can only assume we did (as that&#8217;s our only - allowed - way to work).</p>

<p>What&#8217;s happening now we would like to revert that feature? We must read all the history searching for the very first change involved in that feature (and as things are so perfectly aweful the commits are not only focusing on the feature we implemented, so we must alread read all the code changed) and revert changes carefully each one at a time&#8230;</p>

<p>So now, not only we do branches but also we do non fast forward merges to ensure we see the merge in the history.</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>git merge --no-ff</span></code></pre></td></tr></table></div></figure>


<p>As a result, it&#8217;s now easy to spot what is the involved changeset, and also we can just revert the <em>entire branch</em> easily.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Introducing Live-Note appspot com]]></title>
    <link href="http://franck.verrot.fr/blog/2010/03/04/introducing-live-note-appspot-com/"/>
    <updated>2010-03-04T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/03/04/introducing-live-note-appspot-com</id>
    <content type="html"><![CDATA[<p>I was about to call this article &#8220;Gemcutter Webhooks on Google Wave (and Google App Engine) part 2&#8221; but then I realized that it was no more about that I wanted to focus on, but more on the Wave part (sorry Rubyists friends, but I had fun with Python (as long as I don&#8217;t try to do metaprogramming Python is nice to play with :)).</p>

<p>Google released the Google Wave Robot API v2 (hurray). In that major revision, they are introducing the Active Robot API that makes it possible for robots (i.e. GAE-baked applications) to interact with Waves. In the previous version, your robot was being notified each time a wave (or wavelet, or blip) was modified or when a participant was added to the wave, but now, your application can actually be active and contact Wave on its own.</p>

<p>In the first part of this series of articles, I was demonstrating how to build a GAE-baked application and how to subscribe to a web hook (being a Rubyist I was taking the webhooks from Gemcutter / Rubygems.org). I went only half-way as I wanted to actually see the result <em>inside</em> Google Wave. But then I think to my self, what a wonderful <del>world</del> think it would be to do something actually useful in my everyday life instead of just demonstrating mix of technologies (even if it&#8217;s neat to be able to make applications talk to each others).</p>

<p>So today, it&#8217;s gonna be about a 12-hour-design application: <strong>Live-Note</strong>.</p>

<!--more-->


<p>When I first created &#8220;Gemhooker&#8221;:http://gemhooker.appspot.com, GAE was kinda new for me and I was learning all about it. Even understanding how to plug request handlers within a Google Robot application was hard. But after a lot of investigations, I was able to create in no-time an app able to understand 3 over the 5 communication mediums: email, chat and web app forms. The only missing forms of communications are voice and video.</p>

<p>And this app, is <strong>Live-Note</strong>. I tried to use &#8220;280slides&#8221;:http://www.280slides.com for this:</p>

<iframe width="400" height="328" src="http://280slides.com/Viewer/?user=34211&name=Live-Note" style="border: 1px solid black; margin: 0; padding: 0;"></iframe>


<p>It&#8217;s still in beta, and is likely to stay as it is for a while because I won&#8217;t have anytime to update it in the future weeks/months, but you can already work with it. I tried to do something nice using IUI, that emulates the iPhone GUI, but I gotta admit I can improve that a little bit :)</p>

<p>To wrap up:</p>

<ul>
<li>First time use: http://live-note.appspot.com</li>
<li>Then Chat with <em>live-note@appspot.com</em></li>
<li>Or Mail <em>live-note@live-note.appspotmail.com</em></li>
<li>Or Use the &#8220;web app&#8221;:http://live-note.appspot.com</li>
</ul>


<p>And of course, feel free to give your feedback!</p>

<p><strong>Edit: I fixed the chat username and email&#8230; sorry about that :)</strong></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Rails 3 Let ActiveRecord Manage Your Translations]]></title>
    <link href="http://franck.verrot.fr/blog/2010/02/27/rails-3-let-activerecord-manage-your-translations/"/>
    <updated>2010-02-27T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/02/27/rails-3-let-activerecord-manage-your-translations</id>
    <content type="html"><![CDATA[<p>With the previous versions of Rails we have the choice between storing the translations into a YAML file (one per language) and standard Ruby Hashes.</p>

<p>Bringing the ActiveRecord backend to light, the I18n gem allows us now to manage all our translations in a regular database.</p>

<p>The I18n gem (required to run Rails 3) has been released in late December and is providing all you need to store your translations into a database. A neat thing is the I18n::Backend::Base module, which makes it easy to start writing a new backend in no time.</p>

<p>Today we&#8217;ll just configure our Rails 3 application to start storing our translations in our ActiveRecord-baked database.</p>

<p>First of all, let&#8217;s create a database table that will be used for the translations. Fire up a new migration and fill-in the blanks in <em>self.up</em> with:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">create_table</span> <span class="ss">:translations</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
</span><span class='line'>  <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:locale</span>
</span><span class='line'>  <span class="n">t</span><span class="o">.</span><span class="n">string</span> <span class="ss">:key</span>
</span><span class='line'>  <span class="n">t</span><span class="o">.</span><span class="n">text</span>   <span class="ss">:value</span>
</span><span class='line'>  <span class="n">t</span><span class="o">.</span><span class="n">text</span>   <span class="ss">:interpolations</span>
</span><span class='line'>  <span class="n">t</span><span class="o">.</span><span class="n">boolean</span> <span class="ss">:is_proc</span><span class="p">,</span> <span class="ss">:default</span> <span class="o">=&gt;</span> <span class="kp">false</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This table is required by I18n, but its structure obviously evolve for your own needs. You should now also create a model in <em>app/models/translation.rb</em>:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Translation</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Now you can migrate (<em>rake db:migrate</em>), open up your <em>config/application.rb</em> file and modify it to make it looks like this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">[.</span><span class="n">.</span><span class="o">.]</span>
</span><span class='line'><span class="k">module</span> <span class="nn">YourApplicationName</span>
</span><span class='line'>  <span class="k">class</span> <span class="nc">Application</span> <span class="o">&lt;</span> <span class="no">Rails</span><span class="o">::</span><span class="no">Application</span>
</span><span class='line'>  <span class="o">[.</span><span class="n">.</span><span class="o">.]</span>
</span><span class='line'>    <span class="no">I18n</span><span class="o">.</span><span class="n">backend</span> <span class="o">=</span> <span class="no">I18n</span><span class="o">::</span><span class="no">Backend</span><span class="o">::</span><span class="no">ActiveRecord</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>  <span class="o">[.</span><span class="n">.</span><span class="o">.]</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Voilà! To start creating some translations you can open a Rails console and :</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Translation</span><span class="o">.</span><span class="n">create!</span><span class="p">(</span><span class="ss">:locale</span> <span class="o">=&gt;</span> <span class="s2">&quot;en&quot;</span><span class="p">,</span> <span class="ss">:key</span> <span class="o">=&gt;</span> <span class="s2">&quot;activerecord.models.user&quot;</span><span class="p">,</span> <span class="ss">:value</span> <span class="o">=&gt;</span> <span class="s2">&quot;my user&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p><em>[Edit: Feb 28th]</em> : Cédric and Nicolas got it right: you&#8217;re gonna run into a lot of troubles if you hit the database each and every time you need a translation. A solution to that: caching. How to proceed? Just again your <em>config/application.rb</em> and add:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">[.</span><span class="n">.</span><span class="o">.]</span>
</span><span class='line'><span class="no">I18n</span><span class="o">.</span><span class="n">backend</span> <span class="o">=</span> <span class="no">I18n</span><span class="o">::</span><span class="no">Backend</span><span class="o">::</span><span class="no">ActiveRecord</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'><span class="no">I18n</span><span class="o">::</span><span class="no">Backend</span><span class="o">::</span><span class="no">ActiveRecord</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:include</span><span class="p">,</span> <span class="no">I18n</span><span class="o">::</span><span class="no">Backend</span><span class="o">::</span><span class="no">Cache</span><span class="p">)</span>
</span><span class='line'><span class="no">I18n</span><span class="o">.</span><span class="n">cache_store</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Cache</span><span class="o">.</span><span class="n">lookup_store</span><span class="p">(</span><span class="ss">:memory_store</span><span class="p">)</span> <span class="c1"># or whatever store you prefer</span>
</span></code></pre></td></tr></table></div></figure>


<p>Ain&#8217;t it great? :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Executing binary files with Ruby on Rails and Heroku]]></title>
    <link href="http://franck.verrot.fr/blog/2010/02/24/executing-binary-files-with-ruby-on-rails-and-heroku/"/>
    <updated>2010-02-24T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/02/24/executing-binary-files-with-ruby-on-rails-and-heroku</id>
    <content type="html"><![CDATA[<p>One would easily wonder why in hell someone else would want to do that, but it&#8217;s actually often because you are forced to.</p>

<p>In this post, I&#8217;ll explain how to proceed.</p>

<!--more-->


<p>That&#8217;s not the kind of thing you usually do and it&#8217;s actually during the implementation of an online boutique that made me hit the issue.</p>

<h4>1. A matter of time in the beginning&#8230;</h4>

<p>Some banks have unobtrusive systems. They give you a very detailed specification of how to build the form that will allow your visitor to connect to the payment gateway and also, how to verify after the payment processing whether or not the payment has been successful.</p>

<p>Some others require to execute a binary file (with a couple of special parameters and files that must be relative to the Rails&#8217; app root) that will return the actual HTML form.</p>

<h4>2. &#8230; and a matter of hidden technical debt at the end.</h4>

<p>As one would imagine it&#8217;s easier to really on the second option, but it also means that <em>your hosting platform is now tight-coupled to your application</em> and in the cloud-oriented future that is ours, it seems like you&#8217;re building your own time bomb but you don&#8217;t really know when it&#8217;s gonna blow out.</p>

<p>In any case, you&#8217;re still gonna need to actually execute a program so the underlying hosting plateform must be known and your binary must run on it.</p>

<h4>3. The right choice.</h4>

<p>In fact the choice is not entirely yours when you rely on someone else&#8217;s binary, but hopefully some operating systems are more or less recognized as standards: Debian-based GNU/Linux distributions, Red Hat&#8217;s, and Windows.</p>

<p>Saying that everybody can just go for Heroku would be misleading, but their stack is 100% business standard and unmodified (understand: if it&#8217;s working in-house, it&#8217;s working in the cloud).</p>

<h4>4. Executing a binary in Ruby</h4>

<p>That was actually the reason we&#8217;re here. If you made that far it&#8217;s only because you wanted to run one, so let&#8217;s get going. To effectively call the program you can use different methods as:</p>

<script src="http://gist.github.com/315103.js?file=executing+a+binary+on+heroku+part+2.rb"></script>


<h4>5. Executing a binary in a Ruby application</h4>

<p>I really prefer the @Open3.popen3@ call cause it gives access to the well-known standard Unix I/O. But they all work and you can pick any of these given your own requirements.</p>

<p>First of all, create a directory at the root of your Ruby application called @bin@ and add it to your git repository:</p>

<script src="http://gist.github.com/315087.js?file=executing+a+binary+on+heroku+part+1.sh"></script>


<p>Let me emphasize the last sentence: <em>you must put in the @bin@ directory at the root of your application and make it executable</em>.</p>

<p>You already know how to call your executable (or you should read again the beginning of the post :)). So let&#8217;s embed it in your model but I won&#8217;t cover that topic as it&#8217;s quite framework-related and  we&#8217;re not here to talk about frameworks.</p>

<h4>6. Wrap up</h4>

<ul>
<li>The @bin@ directory at the root of your application.</li>
<li>The executable flags have to be set up.</li>
<li>Any of the described way of executing a binary will work, pick your favorite.</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Talk to Gemcutter's API using XMPP/Google Talk]]></title>
    <link href="http://franck.verrot.fr/blog/2010/02/20/talk-to-gemcutters-api-using-xmppgoogle-talk/"/>
    <updated>2010-02-20T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/02/20/talk-to-gemcutters-api-using-xmppgoogle-talk</id>
    <content type="html"><![CDATA[<p>Working with Ruby in my day job made me try other exciting things, especially with Google App Engine. Programming in Python is not so bad, but I won&#8217;t say I&#8217;m having fun remapping my brain onto the weirdosities of the language.</p>

<p>Anyhoo&#8230; Tonight I wanted to talk to Gemcutter, but not programmatically, I wanted to have it in my GTalk contact list and start having a little chat&#8230;</p>

<p>The very first step was to fire up a new application in App Engine web panel. Five seconds later, let&#8217;s fired up a GVim and create (within a new directory) app.yml and gemtalker.py.</p>

<p>Let&#8217;s start with the app.yml:</p>

<script src="http://gist.github.com/309578.js?file=app.yml+to+enable+XMPP+in+AppEngine"></script>


<p>~Mind the <em>inbound_services</em> declaration~</p>

<p>Now fill-in some code in your main python file:</p>

<script src="http://gist.github.com/309577.js?file=Talk+to+your+App+Engine+application"></script>


<p>As one would notice it&#8217;s pretty easy to play with XMPP services and actually, we need to know very few things here (as we don&#8217;t even handle user registration to secure application access, etc&#8230;):
* It&#8217;s all in the request object;
* Replying is a no-brainer.</p>

<p>Now we must interact with Gemcutter&#8217;s API to get some information (that was the purpose of this article actually&#8230;). I&#8217;m not a real Pythonista, so I didn&#8217;t know how to make this more readable/simpler but please, don&#8217;t hesitate to fork me hard on <a href="http://github.com/cesario/gemtalker">Github</a>.</p>

<script src="http://gist.github.com/309585.js"></script>


<p>I must admin I wanted to use method_missing but it&#8217;s a&#8230; method missing in Python (I found a way to do it thought but that&#8217;s gonna be for later on).</p>

<p>So let&#8217;s wrap it up:</p>

<ul>
<li>Gemcutter&#8217;s library: done;</li>
<li>XMPP library: ready;</li>
</ul>


<p>So we&#8217;re up for wiring it up and writing the logic behind the application.</p>

<p>I&#8217;ll let read the draft implementation of all of this on <a href="http://github.com/cesario/gemtalker/">Github</a> , but it&#8217;s already up and running and you can invite gemtalker@appengine.com in Google Talk and use the &#8221;<em>info</em>&#8221; command.</p>

<p>What&#8217;s mising:
* Activate the <em>AUTH</em> command and store api keys only for the current session
* Search a gem
* Modify webhooks, owners, etc&#8230; (requires the AUTH to be done)</p>

<p>Have fun!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Gemcutter Webhooks on Google Wave (and Google App Engine) part 1]]></title>
    <link href="http://franck.verrot.fr/blog/2010/01/27/gemcutter-webhooks-on-google-wave-and-google-app-engine-part-1/"/>
    <updated>2010-01-27T00:00:00+01:00</updated>
    <id>http://franck.verrot.fr/blog/2010/01/27/gemcutter-webhooks-on-google-wave-and-google-app-engine-part-1</id>
    <content type="html"><![CDATA[<p>So what are Gemcutter webhooks? It&#8217;s a way to automatically notice an online app (say gemhooker.appspot.com for instance) about the activities of your favorite (or all) Gemcutter&#8217;s gems&#8230;</p>




<p>As mentioned in the <a href="http://gemcutter.org/pages/gem_docs#webhook">documentation</a>, let&#8217;s install gemcutter&#8217;s gem if not already done:</p>


<p></p>

<script src="http://gist.github.com/271511.js"></script>


<p>Now this is done, let&#8217;s get it started and fire up a new Python&#8217;s powered <span class="caps">GAE</span> app (gemhooker.py):<br /> 
<script src="http://gist.github.com/271504.js"></script></p>


<p></p>

<p>If you deploy this app (with appcfg.py update gemhooker-clone-you-just-initialized), you won&#8217;t see anything so let&#8217;s ask Gemcutter to add a webhook that will notice our app everytime someone pushes changes onto Gemcutter! I&#8217;m subscribing to every event of all the existing gems:</p>


<p></p>

<script src="http://gist.github.com/271507.js"></script>


<p>You can see the result on <a href="http://gemhooker.appspot.com">gemhooker.appspot.com</a>.</p>


<p></p>

<p><a href="http://twitter.com/qrush">Nick Quanranto</a> has done it (and it looks good, really good job!) using Ruby and deployed it on <a href="http://gemwhisperer.heroku.com">Heroku</a>.</p>


<p></p>

<p>I wish I could have done this with Ruby too but as I need to make it work with Wave (and it seems like a <span class="caps">PITA</span> to make Rails 2.x work on AppEngine), I&#8217;ll suffer till the end of this project :)</p>


<p></p>

<p>In part 2, I&#8217;ll explain how to make a Wave Gadget.</p>


<p></p>
]]></content>
  </entry>
  
</feed>

