<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>codigo ergo sum</title>
 <updated>2010-06-06T06:36:11-07:00</updated>
 <id>http://codigoergosum.com/</id>
 <author>
   <name>Balint Erdu</name>
   <email>balint@codigoergosum.com/</email>
 </author>
 
 
 <entry>
   <title>It's a spec, not a test</title>
   <link href="http://codigoergosum.com/2010/06/03/its-a-spec-not-a-test.html"/>
   <updated>2010-06-03T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2010/06/03/its-a-spec-not-a-test</id>
   <content type="html">&lt;p&gt;You must have heard the question several times on the Rails mailing list and different IRC channels: &quot;Should I test validates_uniqueness_of&quot;? The standard answer to that one is &quot;No, you definitely should not. It's Rails framework code, and it's already thoroughly tested. If you followed this path, you should also test whether objects are properly persisted in the database.&quot;&lt;/p&gt;

&lt;p&gt;I think, however, that the question is wrong and thus you can not give a correct answer. It is wrong because validates_uniqueness_of is the implementation, not the requirement. If you approach it from this angle, the question turns into whether you should test the specific implementation or whether you should verify that (business) requirements are met.&lt;/p&gt;

&lt;p&gt;That, in turn, comes down to tests vs. specs (short for specifications) and this is again an opportunity for specs to shine. If you write specs instead of tests (or, to put it in a more mind-warping way: if your tests are actually specs), then the above question is a no-brainer: it's part of the specification that no two users can have the same email address, so you must have a spec for it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;has a unique email address&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;jeff@topnotch.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;jeff@topnotch.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt;
     &lt;span class=&quot;n&quot;&gt;raise_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RecordInvalid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;On the other hand, if you stick with calling your tests tests (how orthodox! ;) ) then not only you have to think (which consumes a lot of resources), but you can also come to the wrong conclusion and emit a strong business requirement from your test suite. And then you might not remember to have the implementation for it after modifying the code for whatever reason. And then bad things might happen.&lt;/p&gt;

&lt;p&gt;(This thought came to me when coming to work in the subway this morning. I was never quite comfortable with the name &quot;specs&quot; but now it's starting to make a lot of sense to me. You are encouraged to disagree. Dissent is what makes the world progress.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Remove'em trailing whitespaces!</title>
   <link href="http://codigoergosum.com/2010/02/16/remove-trailing-whitespaces.html"/>
   <updated>2010-02-16T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/02/16/remove-trailing-whitespaces</id>
   <content type="html">&lt;p&gt;Some of you reading this probably use TextMate. It is an excellent editor with two caveats. The first is that you can only see one file in the editing window (no screen split), the other is that there is no save hook. This latter gave me headaches since I can't stand any trailing whitespace in source code and the easiest solution would have been to run a script to remove those when the file is saved.&lt;/p&gt;

&lt;p&gt;Without further ado I'll paste my solution below. Obviously this is not a difficult task to accomplish so the goal is to share not to show off. I use Git for SCM and the following solution parses out the files that have been modified and runs the whitespace eraser script for those. If you use something else (why do you?) you should obviously change the first building block:&lt;/p&gt;

&lt;p&gt;parse_modified_files_from_git_status.rb&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env ruby -wn&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;modified_file_pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/^#\s+(?:modified|new file):\s+(.*)$/&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$1&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modified_file_pattern&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$_&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;rm_trailing_whitespace.rb&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env ruby -wn&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;__FILE__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;trailing_whitespace_eraser&amp;quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;TrailingWhiteSpaceEraser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rm_trailing_whitespace!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;trailing_whitespace_eraser.rb&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TrailingWhiteSpaceEraser&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;FILE_TYPES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;rb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;feature&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;yml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;erb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;haml&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rm_trailing_whitespace_from_file!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;trimmed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readlines&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/[\t ]+$/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;w&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trimmed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rm_trailing_whitespace!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expand_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;directory?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/**/*.{&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;FILE_TYPES&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rm_trailing_whitespace_from_file!&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chomp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And then you run it by typing:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;git status | parse_modified_files_from_git_status.rb | rm_trailing_whitespace.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;If you decide to use this, it is more convenient to &lt;a href=&quot;http://gist.github.com/raw/305654/568290aa63ee3b0b3748b5041654f94ce45f4e5b/erase_trailing_whitespace.rb&quot;&gt;download the raw source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hopefully I did my tiny bit to have less trailing whitespace in OS code.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>2010 is the year of the Javascript</title>
   <link href="http://codigoergosum.com/2010/01/28/2010-is-the-year-of-the-javascript.html"/>
   <updated>2010-01-28T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/01/28/2010-is-the-year-of-the-javascript</id>
   <content type="html">&lt;p&gt;If you've read the &lt;a href=&quot;http://pragprog.com/titles/tpp/the-pragmatic-programmer&quot;&gt;The Pragmatic Progammer - From Journeyman to Master&lt;/a&gt; (and if you have not, believe me, you should) you might remember one precious advice: learn a new programming language every year. So when the year draws close to its end (around April, that is) I really start thinking about which language should be the one for me next year.&lt;/p&gt;

&lt;p&gt;This reflection is very pleasant; it is such a joy to immerse oneself into a new language, to slowly discover its structure, its subtleties and learn new ways of thinking, of approaching a problem (because that's probably the biggest gain of it, even surpassing adding another language to your arsenal) that its prospect is already rewarding in itself.&lt;/p&gt;

&lt;p&gt;My choice in 2009 fell on &lt;a href=&quot;http://clojure.org&quot;&gt;Clojure&lt;/a&gt;. I love functional programming, its elegance, its cleanness, its statelessness and after getting my feet wet with &lt;a href=&quot;http://www.paulgraham.com/acl.html&quot;&gt;ANSI Common LISP&lt;/a&gt; a while ago I felt like Clojure would propel me on my way of becoming an FP guru. Guided by &lt;a href=&quot;http://pragprog.com/titles/shcloj&quot;&gt;a great book&lt;/a&gt; I wrote a couple of, admittedly &lt;a href=&quot;http://github.com/balinterdi/clojure_exercises/blob/master/lzw/compressor.clj&quot;&gt;not too difficult&lt;/a&gt; &lt;a href=&quot;http://github.com/balinterdi/clojure_exercises/tree/master/sudoku/game.clj&quot;&gt;exercises&lt;/a&gt;  (hey, a &lt;a href=&quot;http://github.com/balinterdi/clojure_exercises/tree/master/sudoku/game.clj&quot;&gt;sudoku solver&lt;/a&gt; is already something, isn't it?) and I would certainly like to continue to do more with it in 2010.&lt;/p&gt;

&lt;p&gt;Now, on to 2010.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://mir.aculo.us&quot;&gt;Thomas Fuchs&lt;/a&gt; is certainly right when he predicts that &lt;a href=&quot;http://mir.aculo.us/2010/01/07/web-developments-next-decade/&quot;&gt;Javascript will play an increasingly significant role in web development&lt;/a&gt;. I was definitely wrong when I had thought of JS as an undebuggable, structure- and featureless, incoherent language. Of course, you can write Javascript code that is like this but I now think that -at least in the case of Javascript- this tells more about the craftsman than about the language.&lt;/p&gt;

&lt;p&gt;Make no mistakes, I can already do Javascript! I can miraculously make a check box appear if you click on a link, or update a database record without reloading the page when you press a button and a ton more such wizardry, really. However, I always felt like there was a whole lot more to Javascript than putting some dumb-looking functions in a file and then include it from my html (no, I don't think inlining it makes a difference) and I felt uneasy about my javascript functions just standing there on their own without any apparent belonging to a group or some kind of cohesive force or idea that holds them together.&lt;/p&gt;

&lt;p&gt;My recent enthusiasm comes from the fact that I had to browse through some of the source code of &lt;a href=&quot;http://script.aculo.us/&quot;&gt;scriptaculous&lt;/a&gt; and I really liked what I saw. The enthusiasm &lt;a href=&quot;http://www.codigoergosum.com/2008/10/09/javascript-method-chain.html&quot;&gt;is not totally new&lt;/a&gt; but looking at that source code demolished the last shreds of my Javascript skepticism, so to speak. So a year later than &lt;a href=&quot;http://www.rubyrailways.com/learn-at-least-one-new-language-every-year/&quot;&gt;Peter Szinek&lt;/a&gt; I am hopping on the same train: Javascript, here I come! If you have read a good book that enhanced your Javascript foo, please tell me about it in the comments.&lt;/p&gt;

&lt;p&gt;And you? Have you already chosen your language for 2010?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Twuckoo 0.3.5 - With email notification</title>
   <link href="http://codigoergosum.com/2010/01/26/twuckoo-0.3.5-with-email-notification.html"/>
   <updated>2010-01-26T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/01/26/twuckoo-0.3.5-with-email-notification</id>
   <content type="html">&lt;p&gt;As some of you might know, I am running a &lt;a href=&quot;http://twitter.com/pragthinklearn&quot;&gt;few&lt;/a&gt; &lt;a href=&quot;http://twitter.com/daily_oblique&quot;&gt;twitter&lt;/a&gt; &lt;a href=&quot;http://twitter.com/wikipedia_tfa&quot;&gt;channels&lt;/a&gt; that use my brainchild, &lt;a href=&quot;http://github.com/balinterdi/twuckoo&quot;&gt;twuckoo&lt;/a&gt;, to periodically send a tweet.&lt;/p&gt;

&lt;p&gt;In &lt;a href=&quot;http://twitter.com/pragthinklearn&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;http://twitter.com/daily_oblique&quot;&gt;of&lt;/a&gt; these cases the program takes its next message from a file and takes care not to tweet the same thing twice by keeping track of the messages already sent. This means, however, that the pool of sendable messages are depleted after a while and the script simply does not send any more tweets, the channel becomes dead.&lt;/p&gt;

&lt;p&gt;This has happened a couple of times in the past and I only realized it with a few days of delay which is kind of awkward (if you were subscribed to one of these accounts, I apologize). So I decided to have twuckoo send a notification in this case so I can go in and refill its queue. Hence twuckoo version 0.3.5 was born which sends an email to the address set in the configuration file when it failed to send a message.&lt;/p&gt;

&lt;p&gt;To install it, add &lt;a href=&quot;http://gemcutter.org&quot;&gt;gemcutter&lt;/a&gt; to the list of gem sources if you haven't already:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; --add http://gemcutter.org
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;And install twuckoo:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;gem install twuckoo
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You might be thinking that it would be more straightforward to have the program replenish itself so that no intervention from the part of the developer is needed. And you would be right, this could be a task for the next version. I still think it is a good idea to send a notification so the (wo)man in charge knows it happened.&lt;/p&gt;

&lt;p&gt;So go ahead, have a look at &lt;a href=&quot;http://github.com/balinterdi/twuckoo&quot;&gt;the README&lt;/a&gt;, set up your own twitter channel and don't fret about when the queue would run dry. You'll be notified.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>My tech book list for 2009</title>
   <link href="http://codigoergosum.com/2010/01/11/my-tech-book-list-for-2009.html"/>
   <updated>2010-01-11T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/01/11/my-tech-book-list-for-2009</id>
   <content type="html">&lt;p&gt;The title probably tells it all, below is the list of technical books I read in 2009. I am -unfortunately :)- not getting paid for any recommendation that lies herein.&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://www.pragprog.com/titles/mjwti/&quot;&gt;My Job Went to India&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Chad Fowler&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;This one is a real motivation booster. Or it might function like love in the case of separated lovers: if you were motivated in the first place, you'll get a kick out of this book and want to do everything it recommends right from the next day. If you were not it might depress you to have to do so many things to stay afloat. Full of useful advices mostly drawn from the author's personal experience in India. 5/5!&lt;/p&gt;

&lt;p&gt;(There is a second, reworked version under the name: &lt;a href=&quot;http://pragprog.com/titles/cfcar2/the-passionate-programmer&quot;&gt;The Passionate Programmer&lt;/a&gt;, you should probably buy that one.)&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://www.joelonsoftware.com/uibook/fog0000000249.html&quot;&gt;User Interface Design for Programmers&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Joel Spolsky&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;I real like Joel Spolsky's essays both for the content and for his witty style. I laughed out loud on several remarks in this book, too. The book reaffirms how important good UI is, makes it accessible for programmers by giving guidelines and provides some examples of good (and especially bad) examples. Its style makes the &quot;dry&quot; technical stuff fun to read.&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://www.pomodorotechnique.com/resources.html&quot;&gt;The Pomodoro Technique&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Francesco Cirillo&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;A time-management and productivity tool, the Pomodoro Technique is the latest craze. The technique can be summarized in a few paragraphs, the details fill about 40 pages which comprise this book. &lt;a href=&quot;http://www.pomodorotechnique.com/resources/cirillo/ThePomodoroTechnique_v1-3.pdf&quot;&gt;The e-book&lt;/a&gt; can be downloaded for free. Although I do not follow all the advices described in the book fully (like administering the tasks you have done at the end of each day) I think the technique is a great way to achieve focus especially if you have problems with it. (The PragProgs have also recently published &lt;a href=&quot;http://pragprog.com/titles/snfocus/pomodoro-technique-illustrated&quot;&gt;a book about it&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://pragprog.com/titles/shcloj&quot;&gt;Programming Clojure&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Stuart Halloway&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;Clojure is a functional programming language that runs in the JVM (hence the &quot;j&quot;, I guess). This excellent book contains everything you need to know to start (and continue) programming in Clojure from multimethods to infinite sequences, from ways to deal with concurrency to understanding and writing macros. Clojure rocks and so does this book!&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://www.sitepoint.com/books/design1/&quot;&gt;The Principles of Beautiful Web Design&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Jason Beaird&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;I bought this book to be able to do a fancier design than putting black text on white background and using ugly textboxes with Times Roman fonts. It has certainly lived up to this goal and it has some very practical advices and links to resources (I particularly liked the chapter about color). Just as its title says, it explains principles rather than implementation details, which is what I was looking for. That said, I still feel I need another book (and a decent amount of practice, of course) to beam me to the level I had planned to reach before buying it. Any suggestions?&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://www.bookdepository.co.uk/book/9780321146533/Test-Driven-Development&quot;&gt;Test-Driven Development By Example&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Kent Beck&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;A true classic, I reckon this book is a must-read for anyone aspiring to adhere to TDD or in fact for anyone already doing it at any level of mastery. In the first two chapters two distinct functionalities are developed (the first one, the Money example, in Java, the second, the xUnit example, in Python) by tiny steps using TDD, at each step pondering on the problem at hand and giving an explanation of the chosen solution. The third and final chapter deals with TDD patterns and is an invaluable addition to the first two chapters. Now that I am writing about it I feel like I should reread this book in 2010 (and then probably once every year). Red, green, refactor!&lt;/p&gt;

&lt;h2&gt;&lt;a href=&quot;http://pragprog.com/titles/ahptl&quot;&gt;Pragmatic Thinking and Learning&lt;/a&gt; &lt;span class=&quot;author&quot;&gt;&lt;em&gt;by Andy Hunt&lt;/em&gt;&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;The fact that I have not finished only goes to show its splendidness, I simply don't want it to end yet. (I read this in a Paul Graham essay but I can't find it right now). Its subtitle, &quot;Refactor your wetware&quot;, is telling: it shows you how to make yourself more productive by harnessing the innate capabilities of your brain and debugging its intrinsic &quot;bugs&quot;. I guess it is also a very refreshing read because it is about our mind and its workings and not some dry technical stuff. The stories and anecdotes linked to some of the sections makes it easy to recall the message. In fact, I liked this book so much I created a &lt;a href=&quot;http://github.com/balinterdi/twuckoo/&quot;&gt;&quot;twitter mini-framework&quot;&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/pragthinklearn&quot;&gt;a twitter channel&lt;/a&gt; for the concise version of the advices.&lt;/p&gt;

&lt;h2&gt;Life is not just about stubbing, view helpers and achromatic color schemes&lt;/h2&gt;

&lt;p&gt;On a Christmas evening, I sat down on a comfy sofa with &lt;a href=&quot;http://www.amazon.com/R%C3%A9volutions-J-M-G-Cl%C3%A9zio/dp/2070768538&quot;&gt;RÃ©volutions by J.M.G. Le ClÃ©zio&lt;/a&gt; in my hand and was totally immersed in it right from page one. I realized I need occasions like this to repeatedly remind myself how much I miss of life if I only ever read technical books. (Sadly, my list of novels I read last year is a lot shorter than the above one but I heartily recommend you &lt;a href=&quot;http://www.goodreads.com/book/show/128029.A_Thousand_Splendid_Suns&quot;&gt;A Thousand Splendid Suns by Khaled Hosseini&lt;/a&gt; and &lt;a href=&quot;http://www.goodreads.com/book/show/887407.Poisson_D_or&quot;&gt;Poisson d'or by J.M.G. Le ClÃ©zio&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;Any good books you have read?&lt;/h2&gt;

&lt;p&gt;I am also making a (so far, only mental) list of books for this year and would like to hear your opinion, too. So have you read any books lately that you would passionately recommend for others?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>i15r handles non-english source</title>
   <link href="http://codigoergosum.com/2010/01/08/i15r-works-with-non-english-source.html"/>
   <updated>2010-01-08T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/01/08/i15r-works-with-non-english-source</id>
   <content type="html">&lt;p&gt;The other day thinking about how &lt;a href=&quot;http://github.com/balinterdi/i15r&quot;&gt;i15r&lt;/a&gt; could be improved I realized that there are times when the language of the non-internationalized site is not English (surprise, surprise). Add to this that lots of languages have &quot;special&quot; characters, characters that may not be properly found and replaced by the matchers. So I first learned the basics of &lt;a href=&quot;http://blog.grayproductions.net/articles/understanding_m17n&quot;&gt;how Ruby handles encodings&lt;/a&gt; (from &lt;a href=&quot;http://blog.grayproductions.net/&quot;&gt;James Edward Gray's&lt;/a&gt; excellent series) and then adjusted a few matchers to catch those special characters, too. (Note: one can't underestimate the utility of a spec suite that covers most of the code)&lt;/p&gt;

&lt;p&gt;The specs pass but I am pretty certain there are some cases where the matchers might not be up to the task. If you come through such a case, please &lt;a href=&quot;http://github.com/balinterdi/i15r/issues&quot;&gt;submit a bug report&lt;/a&gt;. Since there has been a huge improvement in &lt;a href=&quot;http://blog.grayproductions.net/articles/ruby_19s_string&quot;&gt;string encoding in Ruby 1.9&lt;/a&gt; (basically, strings now have an encoding as opposed to in &lt;a href=&quot;http://blog.grayproductions.net/articles/bytes_and_characters_in_ruby_18&quot;&gt;Ruby 1.8&lt;/a&gt;), there might be some cases where strings are properly internationalized using Ruby 1.9 but not with 1.8.&lt;/p&gt;

&lt;p&gt;So if you think this is a valuable addition or just have not tried i15r yet, go get it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;gem install i15r --source http://gemcutter.org
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>New year, new blog</title>
   <link href="http://codigoergosum.com/2010/01/04/new-year-new-blog.html"/>
   <updated>2010-01-04T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2010/01/04/new-year-new-blog</id>
   <content type="html">&lt;p&gt;I guess it all began with &lt;a href=&quot;http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html&quot;&gt;this blog post&lt;/a&gt;. I saw that there is another way for composing a blog post than typing it into a textarea with a WYSIWYG interface (which is, by the way, never really WYSIWYG). It also seemed a lot cooler, something a &quot;real hacker&quot; would prefer hands down. The decision to switch my blog over to a textarea-free motor has been subconsciously made the time I read that post but the implementation needed a year to be realized. I reckon the final push was to see how easy &lt;a href=&quot;http://lackac.hu/2009/11/19/blog-migralas.html&quot;&gt;the migration of the blog's content&lt;/a&gt; is.&lt;/p&gt;

&lt;h2&gt;The tools&lt;/h2&gt;

&lt;p&gt;I decided to use &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt;, a static-site generator since it integrates nicely with Github and has all the features I need. Being a static-site generator I needed a client-side solution to handle comments. I chose &lt;a href=&quot;http://disqus.com/&quot;&gt;Disqus&lt;/a&gt; because that's the one I knew and liked but there are &lt;a href=&quot;http://intensedebate.com/&quot;&gt;alternatives&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;The process&lt;/h2&gt;

&lt;h3&gt;Content migration&lt;/h3&gt;

&lt;p&gt;I needed continuity and thus migrating the old posts and comments. Fortunately Jekyll includes &lt;a href=&quot;http://wiki.github.com/mojombo/jekyll/blog-migrations&quot;&gt;migration scripts for several blog motors&lt;/a&gt;, among them Wordpress, so that was a piece of cake, everything worked out of the box.&lt;/p&gt;

&lt;p&gt;For the comments, I used &lt;a href=&quot;http://gist.github.com/261852&quot;&gt;a modified version of Lackac's script&lt;/a&gt;, that he so kindly directed my attention to (thank you, Lackac). Clearly it was more work than migrating the posts but nothing to shy away from. (If you plan to switch from Wordpress to Disqus I believe you'll be able to use &lt;a href=&quot;http://gist.github.com/261852&quot;&gt;the script&lt;/a&gt; with a few minor modifications.)&lt;/p&gt;

&lt;h3&gt;New design&lt;/h3&gt;

&lt;p&gt;For my Wordpress blog, I used a design template that looked ok but was in PHP and was a PITA to modify or to add some styling to. Since I am looking to improve my capabilities as a designer I thought designing my own blog would be a suitable task to get my hands dirty with. I am not concealing the fact that I borrowed ideas from &lt;a href=&quot;http://www.briancasel.com/&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;http://tom.preston-werner.com/&quot;&gt;blogs&lt;/a&gt; I liked but hey, they say it's not a shame to copy good ideas so what's wrong with that?&lt;/p&gt;

&lt;h3&gt;Layout, site feed, etc. with Jekyll&lt;/h3&gt;

&lt;p&gt;Have I said I love open source? There is a Jekyll wiki that lists &lt;a href=&quot;http://wiki.github.com/mojombo/jekyll/sites&quot;&gt;Jekyll sites&lt;/a&gt; along with a link to their sources so seeing how to set up my blog with Jekyll was quite straightforward. I guess this was still the most time-consuming part of all but I did not really have to think of anything, the steps are well-defined. (Here is the &lt;a href=&quot;http://github.com/balinterdi/balinterdi.github.com&quot;&gt;source of my blog&lt;/a&gt; if you'd like to take a glimpse.)&lt;/p&gt;

&lt;h3&gt;Buying a Github plan to be able to use a non-github domain&lt;/h3&gt;

&lt;p&gt;If you'd like to host your blog under a custom domain (&lt;a href=&quot;http://codigoergosum.com&quot;&gt;http://codigoergosum.com&lt;/a&gt; instead of &lt;a href=&quot;http://balinterdi.github.com&quot;&gt;http://balinterdi.github.com&lt;/a&gt;) you'll need to buy a Github plan. Starting at 7$/month for the Micro plan it's not an insurmountable obstacle, in fact it costs less than the Wordpress hosting I am moving away from.&lt;/p&gt;

&lt;h2&gt;Changing the name&lt;/h2&gt;

&lt;p&gt;Back in the spring of 2008, returning from the &lt;a href=&quot;http://www.euruko2008.org/&quot;&gt;European Ruby conference&lt;/a&gt; (and having finished &lt;a href=&quot;http://pragprog.com/titles/tpp/the-pragmatic-programmer&quot;&gt;The Pragmatic Programmer&lt;/a&gt; on the train) my mind was buzzing with new ideas and I could not wait to set myself on a craftsman's journey.&lt;/p&gt;

&lt;p&gt;I felt I needed a blog immediately. The hard part of course was coming up with a name. Since I felt it was more important to get something going than to idle on finding the perfect one (I guess we can call this agile, can't we? :)), I launched &lt;a href=&quot;http://bucionrails.com&quot;&gt;http://bucionrails.com&lt;/a&gt;. During the almost two years that have passed since that day I have grown somewhat uncomfortable with that name so I decided to change it. I hope you like &lt;a href=&quot;http://en.wikipedia.org/wiki/Descartes&quot;&gt;the new one&lt;/a&gt; :). (I set up a feed redirection with Feedburner to notify you of the feed URL change after 15 days but you could directly subscribe to the &lt;a href=&quot;http://feeds.feedburner.com/codigoergosum&quot;&gt;new feed now&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;The end result&lt;/h2&gt;

&lt;p&gt;It felt appropriate to start the new year with a new blog and -to my surprise- the switch was a lot easier than I had thought. I hope you, the faithful readers of my blog, welcome the change and ameliorate it with your precious comments.&lt;/p&gt;

&lt;p&gt;Now I am blogging like a hacker, too!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>i15r 0.3.1 is out - now with haml matchers!</title>
   <link href="http://codigoergosum.com/2009/12/14/i15r-031-is-out-now-with-haml-matchers.html"/>
   <updated>2009-12-14T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/12/14/i15r-031-is-out-now-with-haml-matchers</id>
   <content type="html">&lt;p&gt;I've just released a new version of the &lt;a href=&quot;http://github.com/balinterdi/i15r&quot;&gt;i15r gem&lt;/a&gt; which alleviates the tedious task of internationalizing a Rails site by finding the &quot;static&quot; texts and replacing them with I18n message strings.&lt;/p&gt;

&lt;p&gt;The good news -and probably the reason I am writing a blog post about it- is that it can now process &lt;a href=&quot;http://haml-lang.com/&quot;&gt;haml&lt;/a&gt; files, too. This must cheer up those who -like me- have come to like haml so much they now use it for their projects. So &lt;a href=&quot;http://gemcutter.org/gems/i15r&quot;&gt;go get it&lt;/a&gt; and let me know how it works for you.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Rubygems under the hood: hooking into require</title>
   <link href="http://codigoergosum.com/2009/10/28/rubygems-under-the-hood-hooking-into-require.html"/>
   <updated>2009-10-28T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/10/28/rubygems-under-the-hood-hooking-into-require</id>
   <content type="html">&lt;p&gt;(See &lt;a href=&quot;http://bucionrails.com/2009/10/20/rubygems-under-the-hood-introduction/&quot;&gt;the introduction&lt;/a&gt; to the series.)&lt;/p&gt;

&lt;p&gt;When you want to pull in a Ruby library, you require it. The library you require has to be on Ruby's load path ($LOAD_PATH) in order to succeed. So let's see how Rubygems hooks into this process.&lt;/p&gt;

&lt;p&gt;The secret lies in custom_require.rb. You'll see a nice comment near the top.&lt;/p&gt;

&lt;blockquote&gt;
When you call &quot;require 'x'&quot;, this is what happens:
  * If the file can be loaded from the existing Ruby loadpath, it is.
  * Otherwise, installed gems are searched for a file that matches.
If it's found in gem 'y', that gem is activated (added to the loadpath).
&lt;/blockquote&gt;


&lt;p&gt;In fact, that explanation looks so straightforward to me that I doubt if I can add more words to precise it, so let's look at the code together:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Kernel&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gem_original_require&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# :doc:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gem_original_require&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LoadError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_error&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=~&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Regexp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;escape&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;\z/&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Gem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;searcher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
      &lt;span class=&quot;no&quot;&gt;Gem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;= &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;gem_original_require&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;load_error&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Aliasing a method, redefining it and calling the original version from the redefined method is a very familiar pattern if you have read Rails source code (called method chaining).&lt;/p&gt;

&lt;p&gt;So, just as the above description says, if the file can be loaded &quot;without Rubygems&quot; it is and Rubygems never comes into the picture. If not, we make sure that the load error comes from the file not found on the load path and then find the gemspec for that file and activate it.&lt;/p&gt;

&lt;p&gt;Activating it adds it to the load path, so we can call the original require safe in the knowledge that it will now succeed and we won't get another load error this time around (and go into an infinite loop). Clever, heh?&lt;/p&gt;

&lt;p&gt;This is one of the cases when the code is so simple for a moment I think I could have written it myself. With its &amp;lt;10 lines of code Rubygems is empowered to load a myriad of useful Ruby libraries. Isn't this wonderful?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>RubyGems under the hood: Introduction</title>
   <link href="http://codigoergosum.com/2009/10/20/rubygems-under-the-hood-introduction.html"/>
   <updated>2009-10-20T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/10/20/rubygems-under-the-hood-introduction</id>
   <content type="html">&lt;p&gt;I am not sure about you, but one thing I keep bumping into while developing ruby applications is rubygem version conflicts. If you have ever come across &quot;can't activate activesupport (= 2.3.4, runtime) for [], already activated activesupport-2.3.3 for []&quot; type of errors, you might be sympathetic to the cause.&lt;/p&gt;

&lt;p&gt;Since &lt;a href=&quot;http://rubygems.org/&quot;&gt;rubygems&lt;/a&gt; was and is being written by some &lt;a href=&quot;http://chadfowler.com&quot;&gt;excellent&lt;/a&gt; &lt;a href=&quot;http://richkilmer.blogs.com/&quot;&gt;Ruby&lt;/a&gt; &lt;a href=&quot;http://onestepback.org/&quot;&gt;minds&lt;/a&gt; I knew the fault probably lies with me and not with the tool. Being a &lt;a href=&quot;http://manifesto.softwarecraftsmanship.org/&quot;&gt;motivated and proud craftsman&lt;/a&gt; I felt like I needed to know my tools and rubygems is probably the number one tool most of us Ruby developers use on a daily basis.&lt;/p&gt;

&lt;p&gt;I intend to write a mini-series of Rubygems posts. A post will be added to the series when I explore some murky corner of rubygems inner mechanics. Some of the time this will come from a particular problem I come across while coding while on other occasions I might just look into the source code and try to understand what a particular piece of code does.&lt;/p&gt;

&lt;p&gt;Now, I realized that when I read on a blog: &quot;I will go into more detail about X in a forthcoming post&quot;, it is the surest sign that you will never read about X again. At least not on that very blog. And I am not saying this in a mean way, I think it is very natural for our plans to change (&quot;evolve&quot; may sound better) even on the short term. So I am aiming low and hoping to give you more than you expected. (Notice I wrote &quot;mini-series&quot; which may just mean a couple of posts.)&lt;/p&gt;

&lt;h2&gt;Do not set your expectations high&lt;/h2&gt;


&lt;p&gt;I am absolutely not a Rubygems expert so please do not be fooled by the &quot;under the hood&quot; title. This will not be commensurate to &lt;a href=&quot;http://weblog.jamisbuck.org/2006/10/2/under-the-hood-rails-routing-dsl&quot;&gt;Jamis Buck's series on Rails routing&lt;/a&gt;. I do not -yet?- have a deep insight and I am not even a contributor to Rubygems.&lt;/p&gt;

&lt;p&gt;The forthcoming :) series is just a humble attempt to gain an understanding of a very important part of the Ruby arsenal. I hope to understand it better by explaining to you how it works and I hope you will understand it better by reading my explanation. And last, but not least, I hope we'll both spend less time debugging those tricky issues.&lt;/p&gt;

&lt;p&gt;Having said that, I encourage you to participate in the series. Tell me about a particular problem you had with Rubygems. Correct me if I am wrong. Point me to an article where all this is already explained, and much better. Give feedback so this might evolve to be a discussion rather than an academic lecture. Thank you.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Cucumber meets Selenium meets Integrity</title>
   <link href="http://codigoergosum.com/2009/09/25/cucumber-meets-selenium-meets-integrity.html"/>
   <updated>2009-09-25T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/09/25/cucumber-meets-selenium-meets-integrity</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://martinfowler.com/articles/continuousIntegration.html&quot; title=&quot;Continuous Integration&quot;&gt;Continuous Integration&lt;/a&gt; (CI) is a basic building block of any project done in TDD style. In brief, having a CI server properly set up guarantees that developers can rest assured that the application passes all its tests and can thus be deployed at any moment. It does this by sending some kind of a warning if something is broken so it can be fixed immediately.&lt;/p&gt;

&lt;p&gt;Now I noticed that if a CI server is not in the mix right from the beginning of project, chances are it will never be, that was one of the first things I installed on a new Rails project. My server of choice is &lt;a href=&quot;http://integrityapp.com&quot;&gt;Integrity&lt;/a&gt; mostly because it is so easy to set up and quite straightforward to use.&lt;/p&gt;

&lt;p&gt;Ok, so next we need some tests that Integrity will run at each commit and make sure the app can still be built. As a high-level acceptance test framework, I use &lt;a href=&quot;http://cukes.info&quot;&gt;Cucumber&lt;/a&gt;, which plays very nicely with &lt;a href=&quot;http://seleniumhq.org&quot;&gt;Selenium&lt;/a&gt; for automated in-browser testing. Since nowadays even the most basic web application will have some amount of client-side scripting code (that is, javascript) if you really want to test the features of your application you'll need Selenium tests.&lt;/p&gt;

&lt;p&gt;That's when matters get a bit more complicated when it comes to integrating these with the Integrity server. Why? Because on the server you usually don't have the &quot;desktop environment&quot; which is available on the machine you do the development on. By default, you don't run a desktop manager and have a graphic display on a server. A tool called &lt;a href=&quot;http://linux.about.com/cs/linux101/g/xvfb.htm&quot;&gt;xvfb&lt;/a&gt; comes into a picture that emulate a dumb framebuffer so you can still programs that need a graphic display.&lt;/p&gt;

&lt;p&gt;To have some practical guidance, here's what I did on an Ubuntu server to enable all of the above:&lt;/p&gt;

&lt;p&gt;Install java since Selenium runs in the JVM:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;apt-get install java-common sun-java6-jre
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Install firefox since that's what Selenium runs by default and that's a very good choice.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;apt-get install apt-get install firefox
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Install X since that's what the xvfb launches and Xvfb itself.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;apt-get install xorg xserver-xorg
apt-get install xvfb
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Next I found a &lt;a href=&quot;http://wiki.openqa.org/display/SRC/Selenium-RC+and+Continuous+Integration&quot;&gt;wiki&lt;/a&gt; that describes how to launch the Xvfb correctly. Log into the server and do:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;startx -- &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;which Xvfb&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; :1 -screen 0 1024x768x24 2&amp;gt;&amp;amp;1 &amp;gt;/dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;So Xvfb will run on the DISPLAY :1. So far so good. But something was still not quite right. When integrity launched the test suite that included some Cucumber-Selenium tests I received an error message basically saying that no browser sessions could be started. And the solution to that, in fact, is where this post wants to get at.&lt;/p&gt;

&lt;p&gt;After a decent amount of head-scratching and code mining I realized that the Selenium server starts the browser on the same display where the server itself (the jar file) runs. I have found the relevant code that assembles the command that starts the Selenium server in the selenium-client gem and figured it was not meant to be run in graphic hardware-less environment since I saw no options to define which display it should run on. So as an &lt;a href=&quot;http://github.com/balinterdi/selenium-client/commit/37094df174b5c52cb68d041f7dc940e501b3e438&quot;&gt;easy hack I added the hardcoded &quot;DISPLAY=:1&quot; before it&lt;/a&gt; and crossed my fingers.&lt;/p&gt;

&lt;p&gt;Bingo, it worked and I had a green build again! What's more surprising is that it still runs perfectly on my Macbook so it seems to run in (some) graphical environments, too. It seems a bit strange to me to have found so little information on this subject since Rails, Cucumber, Selenium and CI are all en vogue so it is possible that I missed something obvious and there is an easier way to do all this. I am very eager to hear how others set up their CI to run automated-browser features. Do you use another tool, not Selenium? Do you use a CI server with a monitor?&lt;/p&gt;

&lt;p&gt;Anyway, I certainly hope my hackish solution will prove to be useful for some of you TDD-minded developers out there who run their CI on a simple &amp;lt;name of your favorite provider here&amp;gt; slice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; As &lt;a href=&quot;http://lackac.hu&quot;&gt;a fellow developer&lt;/a&gt; and &lt;a href=&quot;http://github.com/ph7&quot;&gt;the author of the selenium-client gem himself&lt;/a&gt; pointed out library code is not the place for enviroment specific settings. Rather, it should go into the application's code. I guess that leaves the choice of putting it into the code of the application you are building or the configuration of the CI server. This latter seemed more clean to me so I put the following line into config.ru in Integrity's directory:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;env&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;DISPLAY&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;:1&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;There is still something left, though. When integrity -or, to be precise, the selenium process that was launched from integrity- wants to access display :1, it will be denied. You need to explicitly enable local connections by putting &quot;localhost&quot; in a file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt; &amp;gt;/etc/X99.cfg
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;, and then using that file as the access records list when you launch the server:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;xinit -- &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;which Xvfb&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt; :1 -screen 0 1024x768x24 -auth /etc/X99.cfg 2&amp;gt;&amp;amp;1 &amp;gt;/dev/null &amp;amp;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;(Note that I launch xinit and not startx as before. startx somehow adds another -auth option which messes things up)&lt;/p&gt;

&lt;p&gt;There, that should do it. It works and there is no code where it does not belong.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A prime example of not eating your own dog food</title>
   <link href="http://codigoergosum.com/2009/07/14/a-prime-example-of-not-eating-your-own-dog-food.html"/>
   <updated>2009-07-14T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/07/14/a-prime-example-of-not-eating-your-own-dog-food</id>
   <content type="html">&lt;p&gt;I realized how 20th century (plus boring and error-prone) it is to write one's invoices by hand. So I went looking for an invoicing application. My expectations were quite low: I wanted one which can be used from my MacBook, has some basic functions that cut down on typing (e.g a client &quot;database&quot;), has a decent design and UI, can make out invoices in different currencies and did not cost more than ~$100.&lt;/p&gt;

&lt;p&gt;It seemed like I have found &lt;a href=&quot;http://www.native.hu&quot;&gt;one&lt;/a&gt;, which, though it had several minor bugs, seemed acceptable, so I purchased the Basic version. Everything went reasonably well until I had to make out my first invoice in euros. It turned out that the Basic version can only make invoices in Hungarian forints in spite of having a couple of other functionalities (e.g set the VAT rate to 0% automatically on invoices made out to EU companies) which made me think it could make it in euros, too.&lt;/p&gt;

&lt;p&gt;Ok, so accounting hell got me again. I sighed and asked the &lt;a href=&quot;http://www.awasoft.hu/&quot;&gt;company&lt;/a&gt; how much it would cost to have this funcionality. I was informed I had to buy the upgrade to the Business version which costs ~$120 more, roughly the double of the original price I paid! That was too much to take, so I went looking for another invoicing application. After all, it should not be an insurmountable task to write such an app, I murmured to myself.&lt;/p&gt;

&lt;p&gt;I did find a &lt;a href=&quot;http://lessaccounting.com&quot;&gt;couple of&lt;/a&gt; &lt;a href=&quot;http://billingsapp.com&quot;&gt;very good&lt;/a&gt; applications which even overdo what I want them to accomplish. However, the Hungarian homologue of the IRS basically shuts out any foreign competitors by regulating very heavily which conditions must be fulfilled by an invoicing application for a Hungarian company to be able to use it. Bummer.&lt;/p&gt;

&lt;p&gt;&quot;There is still a glimmer of hope.&quot; - I thought. I checked the Hungarian scene still thinking it could not be that difficult to meet my expectations. Well, apparently I was wrong. The &lt;a href=&quot;http://szamlazz.hu&quot;&gt;ones&lt;/a&gt; &lt;a href=&quot;http://cipo.hu&quot;&gt;I&lt;/a&gt; &lt;a href=&quot;https://symbion.eu/&quot;&gt;found&lt;/a&gt; are either overcomplicated to use, look like home pages in the 80s or are way too expensive. Sometimes all of these. So I put off the challenge of finding an acceptable piece of software and got back of writing invoices manually.&lt;/p&gt;

&lt;p&gt;Now you might wonder where &lt;a href=&quot;http://en.wikipedia.org/wiki/Eating_one%27s_own_dog_food&quot;&gt;the dog food&lt;/a&gt; is in the story. Well, today I received the invoice from the company of my purchase of the Basic version of the application. It was written manually on an invoice sheet :) That's tantamount of Steve Jobs using a PC with Windows Vista.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>John Doe is dull: the importance of choosing good user names in tests</title>
   <link href="http://codigoergosum.com/2009/07/12/john-doe-is-dull-the-importance-of-choosing-good-user-names-in-tests.html"/>
   <updated>2009-07-12T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/07/12/john-doe-is-dull-the-importance-of-choosing-good-user-names-in-tests</id>
   <content type="html">&lt;p&gt;We, developers, have to come up with user names all the time. In this glorious, pioneer era of TDD, more than ever we have to not only enter them into text fields but write them in test files that are part of the code and thus are clearly visible and permanent.&lt;/p&gt;

&lt;p&gt;So it is important to give good names, but what is a good name like? I am not thinking about the semantics of the name (whether it has accented letters, or if it has two or three parts, etc.) but look at them from a very personal point of view: whether it makes you, the programmer, satisfied with your choice of names or bored with repeating the same old names you used in other projects and even in those projects, you had copied them from somewhere.&lt;/p&gt;

&lt;p&gt;So when writing your first test where a user is needed, stop for a moment and imagine a world which you like and which is amusing in the context of your application's domain (like &lt;a href=&quot;http://www.youtube.com/watch?v=F2kAnTZBnTg&quot;&gt;philosophers playing soccer&lt;/a&gt;, Luddites attending a technology conference, etc.). Pick some names and let the feeling that you have created something instead of just using old, boring names fill you with contentment. Whenever you need an other name, take one from your world. If you need further data (e.g date of birth) about your test users you can even do a little bit of research.&lt;/p&gt;

&lt;p&gt;Though investing energy in this may reduce the time you spend writing code, compared to all the hours you put into a project, it is negligible. Nurturing this &quot;subculture&quot; in your tests can be very entertaining so you have a good time developing and are less prone to boredom. I think it pays off. We, Ruby programmers all know how important it is to be happy while programming and the effect it has on our productivity.&lt;/p&gt;

&lt;p&gt;And besides, do you know of anyone who is called John Doe?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The hashtag (HRT) retweet bot gemified</title>
   <link href="http://codigoergosum.com/2009/07/10/the-hashtag-hrt-retweet-bot-gemified.html"/>
   <updated>2009-07-10T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/07/10/the-hashtag-hrt-retweet-bot-gemified</id>
   <content type="html">&lt;p&gt;A very simple twitter bot that retweeted everything that was tagged by a certain tag was put together for Scotland on Rails '09. Then, &lt;a href=&quot;http://www.jaimeiniesta.com/&quot;&gt;Jaime Iniesta&lt;/a&gt; adapted it for Euruko '09. I then forked from his repository, made a few simplifications and minor improvements and DRY-d its configuration.&lt;/p&gt;

&lt;p&gt;Maybe most importantly I then turned it into [a gem][hashtag_retweet_home] so that configuration files (including the bot's which has the credentials for the twitter account) do not have to be included in the repository.&lt;/p&gt;

&lt;p&gt;I also set up &lt;a href=&quot;http://twitter.com/budapestrb&quot;&gt;a twitter account for the budapest.rb&lt;/a&gt; group where an instance of the HRT bot will post any tweets that have been tagged with #budapestrb. So, my fellow budapest.rb programmers, if you have anything to say about the budapest.rb, just make sure you include the #budapestrb tag in your tweet and watch the HRT bot repeat it.&lt;/p&gt;

&lt;p&gt;To launch your own hashtag retweet bot, just follow the instructions in &lt;a href=&quot;http://github.com/balinterdi/hashtag_retweet_bot&quot;&gt;the README&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Pragmatic Thinking and Learning on Twitter</title>
   <link href="http://codigoergosum.com/2009/07/03/pragmatic-thinking-and-learning-on-twitter.html"/>
   <updated>2009-07-03T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/07/03/pragmatic-thinking-and-learning-on-twitter</id>
   <content type="html">&lt;p&gt;Some of you may be aware of my grandiose plans with my twitter mini-framework named &lt;a href=&quot;http://bucionrails.com/2009/06/22/twuckoo/&quot;&gt;twuckoo&lt;/a&gt;. For my part I am constantly thinking about -hopefully reasonable- ways that it could be used for the better of mankind :)&lt;/p&gt;

&lt;p&gt;The other part of the story is my enthusiasm with Pragmatic Programmers books. I have recently started &lt;a href=&quot;http://pragprog.com/titles/ahptl/pragmatic-thinking-and-learning&quot;&gt;Pragmatic Thinking and Learning&lt;/a&gt; by Andy Hunt which is also a very good one and found the familiar &quot;resuming card&quot; at the end. This card sums up the wisdom of the book in short phrases just so that you can recall what you read quickly. It is a great idea and can be found in other PP books, too.&lt;/p&gt;

&lt;p&gt;So I asked at a PP email address which seemed to be closest to copyright questions whether I have the right to do this. To my surprise, it was the author himself, &lt;a href=&quot;http://blog.toolshed.com/&quot;&gt;Andy Hunt&lt;/a&gt;, who answered me and kindly gave me permission for the book in question. (Once again, thank you, Andy!)&lt;/p&gt;

&lt;p&gt;So there you have it, &lt;a href=&quot;https://twitter.com/pragthinklearn&quot;&gt;a twitter account that will serve you an advice each day&lt;/a&gt; just so that you can &quot;refactor your wetware&quot; (the subtitle of the book) and hopefully help you be a better craftsman.&lt;/p&gt;

&lt;p&gt;And now, my little twuckoo, on to world domination!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>installing ruby on a linode slice</title>
   <link href="http://codigoergosum.com/2009/07/02/installing-ruby-on-a-linode-slice.html"/>
   <updated>2009-07-02T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/07/02/installing-ruby-on-a-linode-slice</id>
   <content type="html">&lt;p&gt;To be able to experiment freely and find a store for my &lt;a href=&quot;http://bucionrails.com/2009/06/22/twuckoo/&quot;&gt;twuckoos&lt;/a&gt; and other goodies I have recently purchased a Linode 360 slice and had Ubuntu 9.04 installed on it. Next thing was setting up ruby (ruby 1.8.6, to be precise).&lt;/p&gt;

&lt;p&gt;When deciding about how to install ruby, in part I wanted to have flexibility but mostly I wanted to feel like I am a professional sysadmin for some hours so I balked at pre-built ruby packages and went with the roll-your-own approach. I'll summarize below the process and some pitfalls I encountered so it might help someone.&lt;/p&gt;

&lt;h2&gt;Some basic tools&lt;/h2&gt;


&lt;p&gt;First, you will need wget (or curl) to download the sources you will need along the way, so:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get install wget&lt;/pre&gt;


&lt;p&gt;Also, before you stare dumbly at the screen (like I did) wondering why can't the stupid machine run make when the Makefile is clearly there in the directory , don't forget to install make:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get install make&lt;/pre&gt;


&lt;h2&gt;Updating the package repos&lt;/h2&gt;


&lt;p&gt;Plus, since we'll be installing packages that are found in the &quot;universe&quot; namespace (or whatever it is called) you should uncomment the below two lines in /etc/apt/sources.list :&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;deb http://us.archive.ubuntu.com/ubuntu/ jaunty universe
deb-src http://us.archive.ubuntu.com/ubuntu/ jaunty universe&lt;/pre&gt;


&lt;p&gt;... and then update your package index:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get update&lt;/pre&gt;


&lt;h2&gt;Installing some packages ruby needs&lt;/h2&gt;


&lt;p&gt;Before we download and build ruby, however, it is recommendable to have the zlib and openssl libraries so ruby can already bind to them. This is one of the things that is a lot easier to see with hindsight, but here I am, blogging this to you:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get install zlib1g zlib1g-dev zlibc
$ sudo apt-get install openssl&lt;/pre&gt;


&lt;p&gt;It turns out from &lt;a href=&quot;http://www.ruby-forum.com/topic/71774&quot;&gt;this thread&lt;/a&gt;, that the zlib bindings are part of ruby since 1.8.6 so you will not need the libzlib-ruby package.&lt;/p&gt;

&lt;p&gt;Now, on to ruby itself.&lt;/p&gt;

&lt;h2&gt;Ruby &amp;amp; Rubygems&lt;/h2&gt;


&lt;pre lang=&quot;bash&quot;&gt;$ wget ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.8.6-p369.tar.bz2
(untar and cd to new directory)
$ ./configure
configure: error: no acceptable C compiler found in $PATH&lt;/pre&gt;


&lt;p&gt;Piece of cake:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get install gcc
$ ./configure
configure: error: in `/home/balint/ruby-1.8.6-p369':
configure: error: C compiler cannot create executables
See `config.log' for more details.&lt;/pre&gt;


&lt;p&gt;A bit harder, but I have quickly found the answer &lt;a href=&quot;http://ubuntuforums.org/showthread.php?t=17033&quot;&gt;here&lt;/a&gt;, and then did:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ sudo apt-get install libc6-dev g++
$ ./configure
$ make
$ sudo make install
$ ruby -e &quot;p 'hello from linode slice'&quot;
&quot;hello from linode slice&quot;&lt;/pre&gt;


&lt;p&gt;Rolling!&lt;/p&gt;

&lt;p&gt;However, we all know that a ruby installation without gems is a toothless tiger (lion?) so we'll install rubygems last, first downloading the source, and then installing it:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ wget http://rubyforge.org/frs/download.php/57643/rubygems-1.3.4.tgz
(untar and cd to new directory)
$ sudo ruby setup.rb&lt;/pre&gt;


&lt;p&gt;If you want to use gems stored on github (and you probably do) it is convenient to add the gem github repository to your gem sources:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ gem source -a http://gems.github.com
$ sudo gem install balinterdi-twuckoo&lt;/pre&gt;


&lt;p&gt;Ok, that's all. I hope you have found this useful.&lt;/p&gt;

&lt;hr /&gt;&lt;em&gt;Note:&lt;/em&gt;


&lt;p&gt;If you receive an error message similar to the following when trying to install a gem:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;/usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- zlib (LoadError)&lt;/pre&gt;


&lt;p&gt;Then you need to install the appropriate lib package and recompile ruby. Go to the directory where you unpacked the ruby source to and do:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;$ make clean
$ make
$ sudo make install&lt;/pre&gt;

</content>
 </entry>
 
 <entry>
   <title>twuckoo - my twitter mini framework</title>
   <link href="http://codigoergosum.com/2009/06/22/twuckoo-my-twitter-mini-framework.html"/>
   <updated>2009-06-22T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/06/22/twuckoo-my-twitter-mini-framework</id>
   <content type="html">&lt;p&gt;I am reading Andy Hunt's excellent Pragmatic Thinking and Learning book. There is a section about so called &quot;oblique strategies&quot;, short, mysterious phrases that exercise your mind and make you look at problems from another perspective (e.g &quot;repetition is a form of change&quot;).&lt;/p&gt;

&lt;p&gt;The suggested intake was once a day and there was a free application that did just this for Apple computers. However, the application was so outdated that I could no longer run it on my laptop. So, I set out to write that application and after a bit of thinking decided to make a twitter account where I (&quot;I&quot; meaning a script that I wrote :) ) would post an oblique strategy each day and then just follow that account. This way, I can also spread the knowledge around.&lt;/p&gt;

&lt;p&gt;Thus &lt;a title=&quot;Twuckoo&quot; href=&quot;http://github.com/balinterdi/twuckoo/tree/master&quot;&gt;Twuckoo&lt;/a&gt; was born. Twuckoo is a simple program (relying on &lt;a href=&quot;http://github.com/cjohansen/twibot/tree/master&quot;&gt;twibot&lt;/a&gt; for communication with twitter) that lets you periodically post a message on a twitter account. It can fetch the messages from a file, from a database, from the web or whereever you want it to retrieve them from. Its very modular in nature so it delegates the task of getting the next message to twitter and storing the posts to the module. here is currently one generic module, the one that fetches them from a file, and one that fetches them from wikipedia's main page. I strongly hope that it is very easy for you to write your own module for your own purpose. Twuckoo aims to follow the &quot;provide-what's-needed-and-then-just-get-out-of-the-way&quot; principle. Go check out &lt;a href=&quot;http://github.com/balinterdi/twuckoo/tree/master&quot;&gt;the README&lt;/a&gt; for further details.&lt;/p&gt;

&lt;p&gt;It's quite easy to install and run. You can find an example for the file-fetcher module at &lt;a href=&quot;http://twitter.com/daily_oblique&quot;&gt;http://twitter.com/daily_oblique&lt;/a&gt; and &lt;a href=&quot;http://twitter.com/wikipedia_tfa&quot;&gt;http://twitter.com/wikipedia_tfa&lt;/a&gt; grabs &quot;Today's Featured Article&quot; from wikipedia and posts the title and the link so you can grow a little wiser each day :)&lt;/p&gt;

&lt;p&gt;Since it is modular it's very extensible. I kept the API very simple so writing modules should be a piece of cake. Each module has to define the following methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;load_tweets&lt;/strong&gt; Loads the messages that can be twittered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;next&lt;/strong&gt; Gets the next message that will be posted.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;store&lt;/strong&gt; Store the tweet after it had been posted.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Once more, I encourage you to scan through &lt;a href=&quot;http://github.com/balinterdi/twuckoo/&quot;&gt;the README&lt;/a&gt;, devise your own module and let me know about it. Any feedback is very welcome.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; For my Hungarian-speaking readers, I gave a &lt;a href=&quot;http://docs.google.com/Presentation?id=dccxt9fm_3g8nf5fm5&quot;&gt;lightning talk about twuckoo&lt;/a&gt; at the latest budapest.rb meetup.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>acts_as_trivia: would you like to play?</title>
   <link href="http://codigoergosum.com/2009/05/18/acts_as_trivia-would-you-like-to-play.html"/>
   <updated>2009-05-18T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/05/18/acts_as_trivia-would-you-like-to-play</id>
   <content type="html">&lt;p&gt;We all love playing games, from poker to soccer, from hide'n seek to ... trivia! I am a great fan of this latter and also of Rails apps so it was kind of natural for me to come up with the idea of using all the data in your Rails app to serve as the basis of trivia questions.&lt;/p&gt;




&lt;p&gt;The ingredients are few and basic. You have a class with an attribute that is comparable and makes sense to compare (the population of states is a good example, the zip code of addresses is a counter-example).&lt;/p&gt;




&lt;h3&gt;Installation&lt;/h3&gt;




&lt;h4&gt;Install the gem&lt;/h4&gt;


&lt;ol&gt;
&lt;li&gt;Install the gem through Rails's config.gem&lt;/li&gt;

&lt;p&gt;Put this: &lt;/p&gt;
&lt;pre code=&quot;bash&quot;&gt;
    config.gem &quot;balinterdi-acts_as_trivia&quot;, :source =&gt; &quot;http://gems.github.com&quot;, 
:lib =&gt; &quot;acts_as_trivia&quot;
&lt;/pre&gt;
&lt;br /&gt;

&lt;p&gt;in your environment.rb and then run &lt;em&gt;rake gems:install&lt;/em&gt; or &lt;em&gt;rake gems:unpack&lt;/em&gt;.&lt;/p&gt;

&lt;li&gt;Install it system-wide with the gem command&lt;/li&gt;
&lt;pre code=&quot;bash&quot;&gt;
  gem install acts_as_trivia --source http://gems.github.com
&lt;/pre&gt;
&lt;/ol&gt;




&lt;h4&gt;Make your app act as a trivia&lt;/h4&gt;


&lt;br /&gt;


&lt;p&gt;You just have to run the provided trivia from the root of your Rails application:&lt;/p&gt;




&lt;pre code=&quot;bash&quot;&gt;
  ./script/generate acts_as_trivia
&lt;/pre&gt;




&lt;h4&gt;Create trivia questions easily from the command line&lt;/h4&gt;


&lt;br /&gt;


&lt;pre code=&quot;bash&quot;&gt;
    ./script.generate acts_as_trivia_record country population name&lt;/pre&gt;


&lt;p&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p style=&quot;margin-top:20px&quot;&gt;This trivia question will be about the &lt;i&gt;population&lt;/i&gt; of &lt;i&gt;countries&lt;/i&gt; and the  &lt;em&gt;name&lt;/em&gt; of each will be used by the provided helpers for the sake of displaying something unique of each country.&lt;/p&gt;




&lt;h4&gt;Create the pages to answer and assess trivia&lt;/h4&gt;




&lt;br /&gt;


&lt;p&gt;The acts_as_trivia gem only aims to provide a clean interface and the logic, so you will have to create the &lt;em&gt;new&lt;/em&gt; controller action of the &lt;em&gt;TriviaAnswersController&lt;/em&gt; and the corresponding view: &lt;/p&gt;




&lt;pre code=&quot;bash&quot;&gt;
  /users/:user_id/trivias/:trivia_id/trivia_answers/new
&lt;/pre&gt;




&lt;p  style=&quot;margin-top:20px&quot;&gt;However, you can take a look at these files in the &lt;a href=&quot;=http://gist.github.com/raw/107361/f31caad451f0cca699288700aa3d98291a259fd1/gistfile1.rb&quot;&gt;rails app generator&lt;/a&gt; or just directly copy them.&lt;/p&gt;




&lt;h3&gt;Get right in the game&lt;/h3&gt;




&lt;p&gt;Instead of going through the above steps, you can use a rails app generator to set up a trivia app quickly: &lt;/p&gt;




&lt;pre code=&quot;bash&quot;&gt;
rails my_shiny_app -m 
http://gist.github.com/raw/107361/f31caad451f0cca699288700aa3d98291a259fd1/gistfile1.rb
&lt;/pre&gt;




&lt;p style=&quot;margin-top:20px&quot;&gt;Once you go through the setup steps of the app generator, you have everything you need to have a functioning trivia app, so you can go to: &lt;/p&gt;




&lt;pre code=&quot;bash&quot;&gt;
  /users/1/trivias/1/trivia_answers/new
&lt;/pre&gt;




&lt;p style=&quot;margin-top:20px&quot;&gt;And if you created model instances you can already answer your first trivia question. For a more technical (and more complete) description, please see &lt;a href=&quot;http://github.com/balinterdi/acts_as_trivia/tree/master&quot;&gt;the README&lt;/a&gt;. Also, since this is a beta version, please make sure to report any bugs you might come across.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>protecting actions of owner-type associations</title>
   <link href="http://codigoergosum.com/2009/05/01/protecting-actions-of-owner-type-associations.html"/>
   <updated>2009-05-01T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/05/01/protecting-actions-of-owner-type-associations</id>
   <content type="html">&lt;p&gt;The actions of a web application basically fall into three categories based on their access rights:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Actions with anonymous access&lt;/li&gt;
&lt;li&gt;Actions the user has to be logged in to access. (authenticated actions)&lt;/li&gt;
&lt;li&gt;Actions the user needs a certain privilege for to access (authorized actions)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;At the implementation level, the first category is obvious, since the actions in this category do not have to be protected. So let's shift our attention to the second and third category and consider how access protection for these can be achieved in Rails applications.&lt;/p&gt;




&lt;p&gt;Both of these are best done with &lt;a href=&quot;http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html&quot;&gt;before filters&lt;/a&gt; since they run before the control is passed to the action's code and provide a DRY way to protect several actions.&lt;/p&gt;




&lt;h3&gt;Authenticated actions&lt;/h3&gt;


&lt;p&gt;Access restriction is quite straightforward once you have a basic libarary that provides a method to see if a user is logged in (see &lt;a href=&quot;http://github.com/technoweenie/restful-authentication/tree/master&quot;&gt;restful-authentication&lt;/a&gt; for a full-scale solution)&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProfilesController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ApplicationController&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before_filter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:login_required&lt;/span&gt; 
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;login_required&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redirect_to&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;login_path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logged_in?&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;




&lt;br/&gt;




&lt;h3&gt;Authorized actions&lt;/h3&gt;




&lt;p&gt;This can be more tricky since there is a great deal of possibilities of what privilege is needed to access a certain action (e.g only admins can see the full user list, only managers can edit the employees' records, etc.).&lt;/p&gt;


&lt;p&gt;I realized there is one very prevalent type, though, the owner-type access. Only the owner of a blog can modify its data, only the user of a profile can edit its attributes, only the leader of a project can set its deadline, etc. The number of these is endless and I bet there are basically no sites where this does not come up.&lt;/p&gt;




&lt;p&gt;Also, the pattern of this access restriction is pretty much the same in all cases. There is the resource to be protected, its owner and the user currently logged in. For access to be granted, the owner of the resource needs to match the current user. So why not extract the pattern to be reused?&lt;/p&gt;




&lt;h3&gt;Only owner&lt;/h3&gt;




&lt;p&gt;Hence the &lt;a href=&quot;http://github.com/balinterdi/only_owner/tree/master&quot;&gt;only-owner plugin&lt;/a&gt; (I know I suck at naming projects) was born. By default, it will create a before filter in the controller which checks if it is the owner that wants to access the resource. If it is, access is granted. Otherwise, the user is redirected to the login path. Convention over configuration makes a lot of sense so to get up and running you only need to do these two things:&lt;/p&gt;




&lt;p&gt;Install the plugin: &lt;/p&gt;


&lt;pre code=&quot;bash&quot;&gt;
./script/plugin install git://github.com/balinterdi/only_owner.git
&lt;/pre&gt;


&lt;br/&gt;




&lt;p&gt;&quot;Tag&quot; the controller to be protected:&lt;/p&gt;


&lt;pre code=&quot;ruby&quot;&gt;
  class ProfilesController &gt; ApplicationController
    only_owner
    (...)
  end
&lt;/pre&gt;


&lt;br/&gt;


&lt;p&gt;That assumes that the profile can reach its user through the user association and that there is a find_profile method in scope in the controller. If your association or the finder method is named otherwise, you can pass the appropriate parameters to define them (:owner and :finder, respectively). As a -sensible, I reckon- convention, all methods in the controller except the new, create, index and show ones will be protected by default. Once again, this can be overridden with the usual :only and :except parameters.&lt;/p&gt;




&lt;p&gt;I encourage you to scan through the &lt;a href=&quot;http://github.com/balinterdi/only_owner/tree/master&quot;&gt;README&lt;/a&gt; for the options and especially, as always, to give me some feedback.&lt;/p&gt;



</content>
 </entry>
 
 <entry>
   <title>upstream or downstream?</title>
   <link href="http://codigoergosum.com/2009/04/27/upstream-or-downstream.html"/>
   <updated>2009-04-27T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/04/27/upstream-or-downstream</id>
   <content type="html">&lt;p&gt;With the proliferation of &lt;a href=&quot;http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html&quot;&gt;middleware applications&lt;/a&gt; the mentions of upstream and downstream servers has intensified so I decided to get to the end of this and find out what exactly an upstream server is. I first looked up &lt;a href=&quot;http://en.wikipedia.org/wiki/Upstream_server&quot;&gt;wikipedia&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
In &lt;a title=&quot;Computer networking&quot; href=&quot;http://en.wikipedia.org/wiki/Computer_networking&quot;&gt;computer networking&lt;/a&gt;, &lt;strong&gt;upstream server&lt;/strong&gt; refers to a &lt;a title=&quot;Server (computing)&quot; href=&quot;http://en.wikipedia.org/wiki/Server_(computing)&quot;&gt;server&lt;/a&gt; that provides service to another server. In other words, upstream server is a server that is located higher in the &lt;a title=&quot;Hierarchy&quot; href=&quot;http://en.wikipedia.org/wiki/Hierarchy&quot;&gt;hierarchy&lt;/a&gt; of servers.
&lt;/blockquote&gt;


&lt;p&gt;Ok, so based on this simplistic definition, a sketch of a request's route to the application server and the response back can be illustrated like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://bucionrails.com/wp-content/uploads/2009/04/request-stack.jpg&quot; border=&quot;0&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this drawing, the middleware is an upstream server to the underlying application since it provides a service to it (be it caching, url mapping, exception handling and &lt;a href=&quot;http://github.com/rack/rack-contrib/tree/master&quot;&gt;plenty of others&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;So now with my definition established, I was looking for examples in the wild that support it. &lt;a href=&quot;http://mwrc2009.confreaks.com/13-mar-2009-11-05-in-a-world-of-middleware-who-needs-monolithic-applications-jon-crosby.html&quot;&gt;Jon Crosby's excellent presentation&lt;/a&gt; at the MountainWest Ruby Conference used upstream in this context as far as I remember. Check one.&lt;/p&gt;

&lt;p&gt;Browsing the source code of &lt;a href=&quot;http://github.com/rtomayko/rack-cache/tree/master&quot;&gt;rack-cache&lt;/a&gt; -which, by the way, I strongly encourage you to do if you want to understand caching (better) or just like the look of clean Ruby code- I realized Ryan Tomayko's definition of upstream coincides with the above one since he uses downstream in the code to refer to the component/application below the rack-cache component. Check two.&lt;/p&gt;

&lt;p&gt;I recently set up an nginx web server as a front end server to a mongrel cluster that runs a Rails application. Ok, so in this case, the nginx server must be the upstream server since requests hit there first and then are passed to the mongrels. One must hear the sound of collapse of cards in my head when I saw the following &lt;a href=&quot;http://wiki.nginx.org/NginxHttpUpstreamModule&quot;&gt;nginx directive&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;upstream production_mongrels &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  server 127.0.0.1:8000;
  server 127.0.0.1:8001;
  server 127.0.0.1:8002;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Hmm, what? Nginx is above the component it provides a load-balancing service to so by any -ok, by my- definition the directive should say &quot;downstream&quot; and not &quot;upstream&quot;.&lt;/p&gt;

&lt;p&gt;I realize that the request arrow on the diagram moving from top to bottom is a matter of convention and that it probably correlates with the fact that most languages write from the top to the bottom. Nevertheless, as far as I know Nginx is made by a Russian guy and Russians write top to bottom, too, so he should still use &quot;downstream&quot; for the directive, now shouldn't he? Or did he simply start to sketch up boxes and arrows from bottom to top for the sake of it when designing his web server?&lt;/p&gt;

&lt;p&gt;Summing up, I think the above described convention is the common one but since it is not standardized there will always be people and software that uses it the other way around. I am not overly confident though, so please tell me about your definition or just point to examples which support or contradict mine.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>have your to_param begin with the record's id</title>
   <link href="http://codigoergosum.com/2009/04/24/have-your-to_param-begin-with-the-records-id.html"/>
   <updated>2009-04-24T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/04/24/have-your-to_param-begin-with-the-records-id</id>
   <content type="html">&lt;p&gt;If you overwrite the to_param method in your model class such that it does not begin with its id, you can be in for a nasty surprise. Let's say you have a User class and you want URLs to contain the user's login instead of its id.&lt;/p&gt;




&lt;pre code=&quot;ruby&quot;&gt;
  class User
    def to_param
      self.login
    end
    ...
  end
&lt;/pre&gt;




&lt;p&gt;And let’s assume you have a user called &quot;bob&quot;. One might think the following works:&lt;/p&gt;




&lt;pre code=&quot;ruby&quot;&gt;
  &gt;&gt; bob = User.find(3)
  =&gt; #&amp;lt;User id: 3, login: &quot;bob&quot;, ...&amp;gt;
  &gt;&gt; User.find(bob.to_param)
  ActiveRecord::RecordNotFound: Couldn't find User with ID=bob
&lt;/pre&gt;




&lt;p&gt;But it does not. That's a problem since URLs are created by calling the to_param method of the model instances composing the path and a standard, nice way of finding the model instance (user in our example) in a controller action is to fetch the id (now: user_id) from the controller. That will quickly lead to error messages of the above form.&lt;/p&gt;




&lt;p&gt;The reason that it does not work is that ActiveRecord's find method will look for a numerical id at the beginning of the argument. It extracts this id and discards anything that comes after it. It then looks up that id in the database and returns the instantiated record. No numerical id results in an error message. The solution from here on is straightforward, have your to_param return a string where the id comes first: &lt;/p&gt;




&lt;pre code=&quot;ruby&quot;&gt;
  class User
    def to_param
      &quot;#{self.id}-#{self.login}&quot;
    end
    ...
  end
&lt;/pre&gt;




&lt;pre code=&quot;ruby&quot;&gt;
&gt;&gt; bob = User.find(3)
=&gt; #&amp;lt;User id: 3, login: &quot;bob&quot;, ...&amp;gt;
&gt;&gt; User.find(bob.to_param)
=&gt; #&amp;lt;User id: 3, login: &quot;bob&quot;, …&amp;gt;
&lt;/pre&gt;




&lt;p&gt;As a splendid way to prove my point but a totally useless piece of information is that you can put any non-numeric value after the id, and find will still find the record:&lt;/p&gt;




&lt;pre code=&quot;ruby&quot;&gt;
&gt;&gt; User.find(&quot;3-be-aware-of-what-you-overwrite-to-param-with&quot;)
=&gt; #&amp;lt;User id: 3, login: &quot;bob&quot;, …&amp;gt;
&lt;/pre&gt;


&lt;p&gt;So I hope you have found this useful, see you in the next episode :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>yes and no in YAML</title>
   <link href="http://codigoergosum.com/2009/04/09/yes-and-no-in-yaml.html"/>
   <updated>2009-04-09T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/04/09/yes-and-no-in-yaml</id>
   <content type="html">&lt;p&gt;I recently needed to display 'yes' and 'no' &quot;internationally&quot; depending on whether the value of a certain attribute is true or false. So I came up with this simple helper method:&lt;/p&gt;

&lt;pre code=&quot;ruby&quot;&gt;
  def to_yes_no(expr)
    expr ? I18n.t('yes') : I18n.t('no')
  end
&lt;/pre&gt;


&lt;p&gt;and the corresponding translations in the yaml file:&lt;/p&gt;

&lt;pre code=&quot;ruby&quot;&gt;
  yes: sí
  no: no
&lt;/pre&gt;


&lt;p&gt;It was so obviously correct and yet it did not work. It kept displaying &quot;true&quot; or &quot;false&quot;. After about an hour spent scratching my head and juggling with yaml files &lt;a href=&quot;http://en.wikipedia.org/wiki/YAML&quot;&gt;I finally realized that YAML recognizes the strings Yes and No (or their lowercase versions)&lt;/a&gt; and handles them as true and false.&lt;/p&gt;

&lt;p&gt;Strictly speaking, one should always put quotes around the strings in the locale yaml files to make sure they are recognized as strings, but it's so much uglier that way. Anyhow, the solution was precisely that:&lt;/p&gt;

&lt;pre code=&quot;ruby&quot;&gt;
  &quot;yes&quot;: &quot;sí&quot;
  &quot;no&quot;: &quot;no&quot;
&lt;/pre&gt;


&lt;p&gt;Now I wonder if this is a case where the grammar designers (or whatever we call YAML) want to be smarter than the programmer. In any case, they were this time :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>finding missing I18n translations with missing_t</title>
   <link href="http://codigoergosum.com/2009/03/25/finding-missing-i18n-translations-with-missing_t.html"/>
   <updated>2009-03-25T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/03/25/finding-missing-i18n-translations-with-missing_t</id>
   <content type="html">&lt;p&gt;A recurring problem in an internationalized Rails project is to see which translations are missing. You could go through all the pages looking for &quot;translation missing: en, user, new&quot; texts. That, however is very tedious and error prone. There may be some texts you don't even see that are missing translation. (like a title of an image).&lt;/p&gt;

&lt;p&gt;A better solution is to write a program that finds these. So that's what I did. I gave it a very imaginative name: &lt;a href=&quot;http://github.com/balinterdi/missing_t/tree/master&quot;&gt;missing_t&lt;/a&gt;. It's darn simple. You first have to install the gem:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
gem install balinterdi-missing_t  
&lt;/pre&gt;


&lt;p&gt;and then from the root of your Rails app you type:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
missing_t
&lt;/pre&gt;


&lt;p&gt;You will see all the I18n strings that do not have translations along with the file they were found in. If you want to restrict your search for a specific language, you provide its language code as the first parameter, like so:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
missing_t fr
&lt;/pre&gt;


&lt;p&gt;For a bit more detailed description, &lt;a href=&quot;http://github.com/balinterdi/missing_t/tree/master&quot;&gt;see the README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Go ahead, give it a try, your app has the right to speak all those beautiful languages out there!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Thrifty - track your expenses easily</title>
   <link href="http://codigoergosum.com/2009/03/17/thrifty-track-your-expenses-easily.html"/>
   <updated>2009-03-17T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/03/17/thrifty-track-your-expenses-easily</id>
   <content type="html">&lt;p&gt;Thrifty is a simple application I have written (and am still writing) in Sinatra that tracks your expenses. You can quickly record each spending you make and assign tags to them so you can group your expenditures easily. You can then see how much you spend in different categories (by tags) possibly narrowed down to a given date interval.&lt;/p&gt;

&lt;p&gt;Anyway, a web app is all about interaction so give it a try &lt;a href=&quot;http://thrifty.heroku.com&quot;&gt;on the test site&lt;/a&gt; or download it from &lt;a href=&quot;http://github.com/balinterdi/thrifty&quot;&gt;its github repo&lt;/a&gt; and run it locally. You'll also find a somewhat detailed README there.&lt;/p&gt;

&lt;p&gt;This is a very early release so I'd appreciate any kind of feedback, be it a bug report, a comment on bad UI or anything you might find worthwhile sharing.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>plans for 2009 - contribute (more) to open source projects</title>
   <link href="http://codigoergosum.com/2009/03/12/plans-for-2009-contribute-more-to-open-source-projects.html"/>
   <updated>2009-03-12T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/03/12/plans-for-2009-contribute-more-to-open-source-projects</id>
   <content type="html">&lt;p&gt;At the start of 2009 my friend Jaime &lt;a href=&quot;http://www.jaimeiniesta.com/2009/01/07/mi-resumen-del-2008&quot;&gt;resumed his previous year&lt;/a&gt; and proposed me to do the same. It seemed a really good idea but somehow it still died down.&lt;/p&gt;

&lt;p&gt;I know it's March now but I reckon it's still ok to do this until December :) I'll attempt to write a mini-series of posts about not so much what I did in 2008 but rather what I would like to achieve in 2009.&lt;/p&gt;

&lt;p&gt;When I started to work full-time with Ruby I also realized the vast possibilities and magnetism of open source projects. I could -and still can- spend hours browsing among different projects on github, peeping into their code, reading related articles, etc.&lt;/p&gt;

&lt;p&gt;So when I set out for this journey one of my tasks naturally became to regularly contribute to a &quot;serious&quot; open source project. When I got acquainted with Merb I also got to know &lt;a href=&quot;http://datamapper.org/doku.php&quot;&gt;DataMapper&lt;/a&gt;, its default ORM. I admired its elegance and coherence and the more I knew of it the more I liked it. So when the maintainer position of a dm-more gem, &lt;a href=&quot;#dm-constraints&quot;&gt;dm-constraints*&lt;/a&gt; seemed to be up for grabs I took the opportunity.&lt;/p&gt;

&lt;p&gt;That was in December and since then I sent in a few patches and merged changes implemented by others. (which I realized could sometimes be a lot more difficult than writing code :) ). I like to do this and have learned -and probably will learn- a lot so one of my plans for 2009 is to continue with dm-constraints and maybe find other open source projects I could contribute to on a regular basis.&lt;/p&gt;

&lt;p&gt;So, if you happen to use DataMapper, which &lt;a href=&quot;http://bucionrails.com/2009/02/12/why-i-love-datamapper/&quot;&gt;I strongly encourage you to do&lt;/a&gt;, and find a bug related to foreign-key constraints, &lt;a href=&quot;http://datamapper.lighthouseapp.com/projects/20609-datamapper&quot;&gt;file a ticket&lt;/a&gt; and assign it directly to me (Balint Erdi). And/or start contributing!&lt;/p&gt;

&lt;h3&gt;Notes&lt;/h3&gt;




&lt;p id=&quot;dm-constraints&quot;&gt;* Dm-more is the meta package that contains everything outside the core functions of DataMapper. Dm-constraints deals with foreign key constraints. If you are familiar with ActiveRecord, it is basically the options you specify with :dependent on an association.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>easily quote passage with Mail in a reply</title>
   <link href="http://codigoergosum.com/2009/03/12/easily-quote-passage-with-mail-in-a-reply.html"/>
   <updated>2009-03-12T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2009/03/12/easily-quote-passage-with-mail-in-a-reply</id>
   <content type="html">&lt;p&gt;That was too long to twitter, so here it goes.&lt;/p&gt;

&lt;p&gt;If you use Mail (OS-X) when replying to a message you can select some text in the email you want to reply to and then hit reply. The new email will only include the text you selected so you don't have to delete all the lines you don't need. I hope someone finds this useful, I really do.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Why I love Datamapper</title>
   <link href="http://codigoergosum.com/2009/02/12/why-i-love-datamapper.html"/>
   <updated>2009-02-12T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/02/12/why-i-love-datamapper</id>
   <content type="html">&lt;p&gt;I wanted to find the last user in alphabetic order of their names in a Merb project that uses &lt;a href=&quot;http://datamapper.org&quot;&gt;Datamapper&lt;/a&gt; (the default ORM in Merb). So I did [&lt;a href=&quot;#love-datamapper-first&quot;&gt;*&lt;/a&gt;]:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
irb(main):020:0&gt; User.all(:order =&gt; [:name]).first.name
 ~ (0.032946) SELECT &lt;column_names&gt; FROM `users` ORDER BY `name` LIMIT 1
=&gt; &quot;Admin User&quot;
&lt;/pre&gt;


&lt;p&gt;Ok, so the default sorting order is ascending but I need the last one. There are two ways to do this. Write an SQL snippet and sneak in &quot;DESC&quot; somewhere or reverse the collection before taking the first element. Since I was not sure how to sneak in &quot;DESC&quot; plus I prefer writing Ruby to writing SQL hands down, I went with the second approach:&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
irb(main):021:0&gt; User.all(:order =&gt; [:name]).reverse.first.name
 ~ (1.033271) SELECT &lt;column_names&gt; FROM `users` ORDER BY `name` DESC LIMIT 1
=&gt; &quot;XX XX&quot;
&lt;/pre&gt;


&lt;p&gt;See what happened? Instead of reverting the collection (which is extra time even if it is done very fast) Datamapper sneaked in that DESC for me! Isn't this just brilliant? Datamapper takes the burden to write SQL off of your shoulders. You can keep writing Ruby statements you presumably love and let Datamapper take care of the SQL reaping both the comfort and the performance gain. [&lt;a href=&quot;#love-datamapper-second&quot;&gt;**&lt;/a&gt;]. Also, likewise your app stays database type agnostic. Note how it is not supposed there is a RDBMS under the ORM layer. It could work with CouchDB, for example (I think there is actually work in progress for a CouchDB adapter). This is not the only reason I like Datamapper so much, so if you are still not convinced, go check out &lt;a href=&quot;http://datamapper.org/doku.php?id=why_datamapper&quot;&gt;some other reasons to use it&lt;/a&gt;.&lt;/p&gt;

&lt;hr&gt;


&lt;h3&gt;Notes&lt;/h3&gt;


&lt;p id=&quot;love-datamapper-first&quot;&gt;* I could have written this one in a simpler way:
&lt;pre lang=&quot;bash&quot;&gt;
irb(main):018:0&gt; User.first(:order =&gt; [:name]).name
 ~ (0.032345) SELECT &lt;column_names&gt; FROM `users` ORDER BY `name` LIMIT 1
=&gt; &quot;Admin User&quot;
&lt;/pre&gt;

But you -or at least I- could not do it for the last element (there is no User.last)

&lt;p id=&quot;love-datamapper-second&quot;&gt;** I am not suggesting not to learn SQL at all. I am all for a know-thy-tools approach (especially it it means not cluttering your markup with javascript :) ). However, having the ORM do obviously good things for you is worth it most of the time.
&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>deep_test to become TDD more easily</title>
   <link href="http://codigoergosum.com/2009/02/11/deep_test-to-become-tdd-more-easily.html"/>
   <updated>2009-02-11T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/02/11/deep_test-to-become-tdd-more-easily</id>
   <content type="html">&lt;p&gt;I am all for &lt;acronym title=&quot;Test Driven Development&quot;&gt;TDD&lt;/acronym&gt;, really. I did not even waver when recently I have been working on a medium-sized Rails project and running the tests after each change took about 60-80 seconds. 60 seconds is still a lot, though, especially if you go through these cycles ~50 times a day (a wild guess). I also believe in very short test-implementation cycles to stay focused so I was starting to think about ways to keep that time down.&lt;/p&gt;

&lt;p&gt;Autotest, part of the &lt;a href=&quot;http://rubyforge.org/projects/zentest/&quot;&gt;Zentest&lt;/a&gt; toolbox is a very good choice. It basically runs all the tests automatically after something has changed in the code and more importantly it only runs the tests it deems affected by the latest change. This helped to reduce the amount of time by reducing the number of tests that were run in each loop.&lt;/p&gt;

&lt;p&gt;Another I think less well-known option is &lt;a href=&quot;http://www.somethingnimble.com/bliki/deep-test&quot;&gt;deep_test&lt;/a&gt; which helps to reduce testing time by increasing computational power. More precisely, it runs the tests through worker threads so you can either benefit from using deep_test if you set it up for a computer network (individual computers take from a pool of tests and then send in the results) or if you have a multi-core computer. Since many of us do nowadays, that stepped up as a viable option.&lt;/p&gt;

&lt;p&gt;It was quite easy to set up and the results it brought were quite remarkable. It reduced the running time of my tests by ~40% (based on a completely unscientific benchmark). One thing I experienced is that it did not really play out well with sqlite although I have not spent a lot of time trying to make it work there. I just switched to mysql and it worked seamlessly. So yeah, the next logical step was to get the better of both worlds: run only the tests that need to be run and run them on as many cores as possible. I will talk about that in a later post.&lt;/p&gt;

&lt;p&gt;I would very much like to hear your experiences and solutions to make TDD a breeze or just plain bearable. I cannot imagine doing real TDD if running tests takes more than a certain time limit, around maybe 90 seconds. Not only you lose a lot of time waiting for the tests to finish, more importantly you fall out of the falling test-implementation cycle, you lose focus, your mind drifts away and then the whole thing probably just does not work.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>simple to-do list in Sinatra</title>
   <link href="http://codigoergosum.com/2009/02/09/simple-to-do-list-in-sinatra.html"/>
   <updated>2009-02-09T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/02/09/simple-to-do-list-in-sinatra</id>
   <content type="html">&lt;p&gt;After Bence Golda's presentation at the last &lt;a href=&quot;http://www.meetup.com/budapest-rb/&quot;&gt;budapest.rb meetup&lt;/a&gt; I decided to build something easy in &lt;a href=&quot;http://www.sinatrarb.com/&quot;&gt;Sinatra&lt;/a&gt; since it seemed so cool and easy to do. And I have to tell you, it really is both.&lt;/p&gt;

&lt;p&gt;With zero prior experience with Sinatra and only a bit of fresh &lt;a href=&quot;http://haml.hamptoncatlin.com/&quot;&gt;HAML&lt;/a&gt; knowledge, &lt;a href=&quot;http://github.com/balinterdi/todo-list/tree/master&quot;&gt;my todolist&lt;/a&gt; was ready in a few hours. What can you do with it? Add todos to your list and delete them when you are done. What features does it have? Unobtrusive javascript :) What does it lack? Obtrusive javascript :) User-related funcionalities, the possibility of having more lists, seeing done todos, etc. Lots of things. But with the ease of development Sinatra provides I am sure that for a simple application like this these could be added quite quickly. And then &lt;a href=&quot;http://tadalist.com/&quot;&gt;tadalist.com&lt;/a&gt; would be running for its money :) (I know, it's free).&lt;/p&gt;

&lt;p&gt;ps. I use an ORM, datamapper to not to have to deal with SQL directly, so you'll have to &quot;gem install dm-core&quot; beyond the sinatra gems if you want to run the app.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>strings as haml render parameters in Sinatra do not work</title>
   <link href="http://codigoergosum.com/2009/02/04/strings-as-haml-render-parameters-in-sinatra-do-not-work.html"/>
   <updated>2009-02-04T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/02/04/strings-as-haml-render-parameters-in-sinatra-do-not-work</id>
   <content type="html">&lt;p&gt;I was intrigued by the simplicity and elegance of Sinatra as presented by Bence Golda at &lt;a href=&quot;http://files.meetup.com/1271139/09-01-22-golda_bence-sinatra.pdf&quot;&gt;the last budapest.rb meetup.&lt;/a&gt;, so I decided to build a simple application with it (I am planning to talk just a little bit more about that in a later post).&lt;/p&gt;

&lt;p&gt;One quick thing I learned the hard way is when generating haml views in Sinatra, you have to use symbols as the name of the view, strings will just be rendered as strings. That was a tough lesson to learn coming from Rails. So while in Rails you can write:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
  def index
    render :action =&gt; :index
  end
&lt;/pre&gt;


&lt;p&gt;or&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
  def index
    render :action =&gt; &quot;index&quot;
  end
&lt;/pre&gt;


&lt;p&gt;In Sinatra, you can only use a symbol to designate the view to be rendered:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
get '/' do
  haml :index
end
&lt;/pre&gt;


&lt;p&gt;Which makes sense, I think, since symbols (unlike strings, see &lt;a href=&quot;#strings-symbols&quot;&gt;below&lt;/a&gt;) with the same name refer to the same entity which is a perfect fit for naming views, now ain't they? Plus, I'll admit I am in love with them symbols, with their colon in the front and all. And when they are syntax highlighted, I melt.&lt;/p&gt;

&lt;div id=&quot;strings-symbols&quot;&gt;
&lt;pre lang=&quot;bash&quot;&gt;
irb(main):002:0&gt; sym1 = :index; sym2 = :index; sym1.object_id == sym2.object_id
=&gt; true
irb(main):003:0&gt; s1 = &quot;index&quot;; s2 = &quot;index&quot;; s1.object_id == s2.object_id
=&gt; false
&lt;/pre&gt;
&lt;/div&gt;



</content>
 </entry>
 
 <entry>
   <title>Shoulda: setup and should blocks and don't wander off the map</title>
   <link href="http://codigoergosum.com/2009/01/28/shoulda-blocks-active-record-macros-and-their-order.html"/>
   <updated>2009-01-28T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/01/28/shoulda-blocks-active-record-macros-and-their-order</id>
   <content type="html">&lt;p&gt;I'm using &lt;a href=&quot;http://www.thoughtbot.com/projects/shoulda/&quot;&gt;shoulda&lt;/a&gt; for testing in a rails project and I wrote this simple test to see if my update action really updated the object and redirected to the appropriate place:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
context &quot;the update&quot; do
  setup do     # 1
    @project = Factory(:project, :director =&gt; @user)
    put :update, :id =&gt; @project, :project =&gt; { :name =&gt; &quot;updated name&quot; }
  end
  # 2    
  updated_project = Project.first(:order =&gt; &quot;created_at DESC&quot;)
  # 3
  should_redirect_to &quot;project_url(updated_project)&quot; # 4
  should &quot;update the attributes&quot; do
    assert_equal(&quot;updated name&quot;, updated_project.name) # 5
  end  
end
&lt;/pre&gt;


&lt;p&gt;To my surprise, I received an &quot;undefined local variable or method 'updated_project' on both tests (#4 and #5). I figured out why and I want to share it with you. In case you are a shoulda expert, you must know the answer already and sorry for wasting your time. On the other hand, if you are new to shoulda like I am, you may find this useful.&lt;/p&gt;

&lt;p&gt;What shoulda does when running a 'should' block is that it runs all the 'setup' blocks of the contexts in which it is nested, from the outside to the inside, so this:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
context &quot;alpha&quot; do
  setup do
    puts &quot;A&quot;
  end
  context &quot;beta&quot; do
    setup do
      puts &quot;B&quot;
    end
    context &quot;gamma&quot; do
      setup do
        puts &quot;C&quot;
      end
      should &quot;work&quot; do
         puts &quot;the only test&quot;
      end
    end
  end
end
&lt;/pre&gt;


&lt;p&gt;Will print&lt;/p&gt;

&lt;pre lang=&quot;bash&quot;&gt;
A
B
C
the only test
&lt;/pre&gt;


&lt;p&gt;Also the area between #2 and #3 in the above test is sort of a no man's land, since it is not in a setup block, so assignments that are executed here are completely useless. You can not use it either for side-effects since it will run before the setup block (#1 above). My advice is to simply put everything in a block, be it a 'setup' or a 'should' one. (the 'should_redirect_to' is a macro that's part of shoulda, it gets expanded into a block, too).&lt;/p&gt;

&lt;p&gt;So here is the same test correctly:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
context &quot;the update&quot; do
  setup do
    @project = Factory(:project, :director =&gt; @user)
    put :update, :id =&gt; @project, :project =&gt; { :name =&gt; &quot;updated name&quot; }
  end
  
  should_redirect_to &quot;project_url(@project)&quot; 
  should &quot;update the attributes&quot; do
    # reload is needed to see the new state
    @project.reload
    assert_equal(&quot;updated name&quot;, @project.name)
  end
  
end
&lt;/pre&gt;


&lt;p&gt;Shoulda is a nice tool. There is only one I know and I like a tad better which is quite similar in structure, &lt;a href=&quot;http://rspec.info/documentation/&quot;&gt;rspec&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>MySQL table types and foreign key constraints</title>
   <link href="http://codigoergosum.com/2009/01/25/mysql-table-types-and-foreign-key-constraints.html"/>
   <updated>2009-01-25T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/01/25/mysql-table-types-and-foreign-key-constraints</id>
   <content type="html">&lt;p&gt;Uff, I have recently spent some time checking foreign key constraints in MySQL and I got a bit upset. The MySQL docs tell you that &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html&quot;&gt;InnoDB tables support foreign key constraints&lt;/a&gt; but that's not the same as saying MyISAM tables do not. More importantly, an error (or at least a warning) should be raised so that I am not relying on something that seems to be there when in fact it is not.&lt;/p&gt;

&lt;p&gt;Here is the raw SQL:&lt;/p&gt;

&lt;pre lang=&quot;sql&quot;&gt;
CREATE TABLE `drivers` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(100)
);


CREATE TABLE `cars` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `plate_number` VARCHAR(12),
  `driver_id` INT,
  FOREIGN KEY (`driver_id`) REFERENCES `drivers`(`id`) ON DELETE CASCADE
);

INSERT INTO drivers(name) VALUES ('bob');
INSERT INTO drivers(name) VALUES ('alice');
INSERT INTO cars(plate_number, driver_id) VALUES ('bbb', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('ooo', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('aaa', 2);
INSERT INTO cars(plate_number, driver_id) VALUES ('lll', 2);
&lt;/pre&gt;




&lt;pre lang=&quot;shell&quot;&gt;
mysql&gt; delete from drivers where id=1;
Query OK, 1 row affected (0.00 sec)

mysql&gt; select * from cars;
+----+--------------+-----------+
| id | plate_number | driver_id |
+----+--------------+-----------+
|  1 | bbb          |         1 | 
|  2 | ooo          |         1 | 
|  3 | aaa          |         2 | 
|  4 | lll          |         2 | 
+----+--------------+-----------+
4 rows in set (0.00 sec)
&lt;/pre&gt;




&lt;pre lang=&quot;sql&quot;&gt;
CREATE TABLE `drivers` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(100)
) ENGINE=INNODB;


CREATE TABLE `cars` (
  `id` INT PRIMARY KEY AUTO_INCREMENT,
  `plate_number` VARCHAR(12),
  `driver_id` INT,
  FOREIGN KEY (`driver_id`) REFERENCES `drivers`(`id`) ON DELETE CASCADE
) ENGINE=INNODB;

INSERT INTO drivers(name) VALUES ('bob');
INSERT INTO drivers(name) VALUES ('alice');
INSERT INTO cars(plate_number, driver_id) VALUES ('bbb', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('ooo', 1);
INSERT INTO cars(plate_number, driver_id) VALUES ('aaa', 2);
INSERT INTO cars(plate_number, driver_id) VALUES ('lll', 2);
&lt;/pre&gt;




&lt;pre lang=&quot;shell&quot;&gt;
mysql&gt; delete from drivers where id=1;
Query OK, 1 row affected (0.00 sec)

mysql&gt; select * from cars;
+----+--------------+-----------+
| id | plate_number | driver_id |
+----+--------------+-----------+
|  3 | ppp          |         2 | 
|  4 | eee          |         2 | 
+----+--------------+-----------+
2 rows in set (0.00 sec)
&lt;/pre&gt;


&lt;p&gt;I know very well one should &lt;a href=&quot;http://bucionrails.com/2008/10/22/postgresql-pg_hbaconf-authentication/&quot;&gt;read the manual before complaining&lt;/a&gt; but I also think software should complain if asked something which it is not capable of doing. -1 for MySQL.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Google Groups tracker using Yahoo Pipes</title>
   <link href="http://codigoergosum.com/2009/01/17/google-groups-tracker-using-yahoo-pipes.html"/>
   <updated>2009-01-17T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/01/17/google-groups-tracker-using-yahoo-pipes</id>
   <content type="html">&lt;p&gt;I -and I suppose most of my developer mates- am subscribed to many Google Groups. When there is a topic I am interested in or a problem I posted or replied to it would be cool to get notified of changes to it. Instead of checking it five times a day to see if someone has commented on it which also slices up the big, continuous chunks of time we programmers need. Also, some groups are littered by spam topics so it would be nice to filter out all the things you are not particularly fascinated about and be left with the things you are.&lt;/p&gt;

&lt;p&gt;Unfortunately, Google Groups does not offer us the possibility of following certain topics (e.g by sending you an email whenever someone added his comment, a la Lighthouse). But there is a solution although I'll admit the one I am describing below is not a particularly cunning or elegant one. If you felt the same pain and found a remedy, I am curious to know what it is, so please leave a comment.&lt;/p&gt;

&lt;p&gt;So, as we all know, the Internet is just a &lt;a href=&quot;http://en.wikipedia.org/wiki/Series_of_tubes&quot;&gt;series of tubes&lt;/a&gt;, so the idea to use Yahoo Pipes to cobble together something came quite naturally. Ladies and gentlement, I created the &lt;a href=&quot;http://pipes.yahoo.com/balinterdi/google_groups_issue_tracker&quot;&gt;Googe Groups issue tracker&lt;/a&gt;. It is capable of tracking two Google groups. You can pass three strings for each one and it generates an RSS of the items whose title have any of the strings you provide.&lt;/p&gt;

&lt;p&gt;I know it has many shortcomings (to say the least). What if you want to track issues for 3 groups or more? More than 3 issues per group? My puny tracker can't do that right now since its &quot;legoed&quot; together from &lt;a href=&quot;http://pipes.yahoo.com/pipes/&quot;&gt;Yahoo Pipes&lt;/a&gt; building blocks and so it's not programmable. You can, however, clone my pipe, expand it to handle more groups or more expressions, enter the groups you want to track and subscribe to the resulting RSS with your reader of choice.&lt;/p&gt;

&lt;p&gt;It may still feel clumsy, since you have to regularly update your strings based on the issues you are interested in. I know a more general solution would be to hack together something that is more manageable and expandable which I might do soon. But it still feels so good from time to time to leave the serious, hard-thinking adult world and build Lego castles. So go ahead, don't be shy, build your own castle and let me know about it! :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; Thanks to Bob, I realized Google has the very option I missed and constructed the pipe for :) However, there can still be some valid scenarios where it can be of service. As per &lt;a href=&quot;http://jaimeiniesta.com&quot;&gt;Jaime's&lt;/a&gt; comment I realized I did not really explain how to run the pipe, so let me do it through an example that is not too contrived:&lt;/p&gt;

&lt;p&gt;Let's suppose you are a &lt;a href=&quot;http://datamapper.org&quot;&gt;DataMapper&lt;/a&gt; expert and you want to help those newbies/impatient people who put 'help' in the title of their post. In that case, you would input http://groups.google.com/group/datamapper in the &quot;Group1 URL&quot; box and &quot;help&quot; in the &quot;Group1 - Title 1&quot; field. At the pipe output you'd only see those posts which have help in their title, then.&lt;/p&gt;

&lt;p&gt;If you want to also see announcements and the convention would be to have [DM] in the title of those posts, you would then enter &quot;[DM]&quot; in the &quot;Group1 - Title 2&quot; field.&lt;/p&gt;

&lt;p&gt;To construct a filter which only lists ruby-quiz related posts on &lt;a href=&quot;http://groups.google.com/group/ruby-talk-google&quot;&gt;http://groups.google.com/group/ruby-talk-google&lt;/a&gt; is left as an exercise to the reader :).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A ruby-style currency converter</title>
   <link href="http://codigoergosum.com/2009/01/17/a-ruby-style-currency-converter.html"/>
   <updated>2009-01-17T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/01/17/a-ruby-style-currency-converter</id>
   <content type="html">&lt;p&gt;Though it is said that we live in a highly-globalized world, all countries still have their own proper currency (with one exception that I know of, the euro) so we still need to convert between them. If one is used to shop online (and one is) the need to get the price in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Hungarian_forint&quot; target=&quot;_blank&quot;&gt;national currency&lt;/a&gt; occurs quite often. Going to a currency converter page is not much of a hassle but it still takes too much time and it seemed an overshoot to use a browser for this task. Inspired by Rails's date calculations extensions (where you could write 3.days.ago), I decided to create something similar and see how much flying to &lt;a href=&quot;http://euruko2009.org/&quot;&gt;Barcelona&lt;/a&gt; or buying a &lt;a href=&quot;http://pragprog.com/&quot;&gt;PragProg&lt;/a&gt; book costs from the command line.&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;

require &quot;net/http&quot;
require &quot;open-uri&quot;
require &quot;hpricot&quot;

# makes 1284.eur.to.usd types of queries possible
class CurrencyConverter
 
  Currencies = { :huf =&gt; &quot;HUF&quot;, :eur =&gt; &quot;EUR&quot;, :usd =&gt; &quot;USD&quot;, :gbp =&gt; &quot;GBP&quot;, :chf =&gt; &quot;CHF&quot; }
 
  # these methods &quot;close&quot; the quote.
  # when they are called, it means all data is ready
  # the quote can be sent.
  class_eval do
    Currencies.each_key do |curr|
      define_method curr do
        @to = curr
        calculate
      end
    end
  end
 
  def initialize(amount, from=nil, to=nil)
    @amount = amount
    @from = from
    @to = to
  end
 
  def send_request_for_quote
   from_as_param = @from.to_s.upcase
   to_as_param = @to.to_s.upcase
   url = &quot;http://xurrency.com/#{[@amount, @from, @to].join('/')}/feed&quot;
   doc = Hpricot(open(url).read)
   (doc/'dc:value').inner_html
  end
 
  def calculate
    send_request_for_quote
  end

  def to
    self
  end
 
end

class Fixnum 
  def method_missing(name)
    CurrencyConverter.new(self, name)   
  end
end
&lt;/pre&gt;


&lt;p&gt;Thanks to ruby's open classes, the code is quite terse (you can also see and download the raw script from &lt;a href=&quot;http://www.pastie.org/362737&quot;&gt;here&lt;/a&gt;). Now you can fire up irb and do all the conversions you want:&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
$ irb -r currency_converter.rb 
irb(main):001:0&gt; 23.eur.to.huf
=&gt; &quot;6473.3500&quot;
irb(main):002:0&gt; 1.usd.to.eur
=&gt; &quot;0.7642&quot;
&lt;/pre&gt;


&lt;p&gt;Or do it through the ruby interpreter:&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
$ ruby -r rubygems -r currency_converter.rb -e &quot;puts 1.eur.to.usd&quot;
1.3085
&lt;/pre&gt;


&lt;p&gt;I find it very pleasing to be able to write &quot;10.eur.to.usd&quot; since it is so close to our spoken, human language. One of ruby's numerous charms.&lt;/p&gt;

&lt;p&gt;My friend, &lt;a href=&quot;http://www.rubyrailways.com/&quot;&gt;Peter&lt;/a&gt; sent a more general solution that uses html scraping with &lt;a href=&quot;http://scrubyt.org/&quot;&gt;Scrubyt&lt;/a&gt; and the conversion capabilities of Google search:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
require 'rubygems'
require 'cgi'
require 'scrubyt'

begin
google_converter = Scrubyt::Extractor.define do
  fetch &quot;http://www.google.com/search?q=#{CGI::escape(ARGV[0])}+#{CGI::escape(ARGV[1])}+to+#{CGI::escape(ARGV[2])}&quot;
  
  google_result &quot;//td[@dir='ltr']&quot; do
    final_result(/= (.+) /)
  end
end
  puts google_converter.to_hash[0][:final_result]
rescue
  puts &quot;Sorry, even *google* can't translate that!&quot;
end
&lt;/pre&gt;


&lt;p&gt;Using this you can convert amounts between any two currencies (distances, weights, etc., everything that Google search can handle):&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
$ ruby conv.rb 30 EUR HUF
&lt;/pre&gt;


&lt;p&gt;It may be swimming against the current but I like solutions that do not need the browser for simple problems like this one. I scratched my itch and hopefully scratched yours, too.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Record your bike trips with Gmap Pedometer</title>
   <link href="http://codigoergosum.com/2009/01/05/record-your-bike-trips-with-gmap-pedometer.html"/>
   <updated>2009-01-05T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2009/01/05/record-your-bike-trips-with-gmap-pedometer</id>
   <content type="html">&lt;p&gt;Though I thought I would only post about technical issues here, I now make an exception. After all, (soft) rules are for breaking occasionally, aren't they?&lt;/p&gt;

&lt;p&gt;So in case you don't know, there is a nice &lt;a title=&quot;Gmap Pedometer&quot; href=&quot;http://www.gmap-pedometer.com/&quot; target=&quot;_blank&quot;&gt;service out there to record your bike trips&lt;/a&gt; that I have recently discovered. It is a Google Maps application where you first search your point of departure then your point of arrival and Gmap Pedometer does the rest for you. Occasionally you have to lend it a helping hand, though, in case the automatic route generation does not work well. It usually does not if you take bicycle roads that does not run paralelly with the highway since the automatic route generation selects the &quot;car route&quot; by default (it seemed to me). You can set up your itinerary in no time and promptly see the distance you did and how much energy you burned during the process (and ultimately also the elevation of your trip).&lt;/p&gt;

&lt;p&gt;I also grab the opportunity to tell you how bike tours are the perfect way of tourism for me. You can easily do 40-50kms per day in a moderate pace. In my opinion that's a perfect middle ground between being too slow and passing by magnificent landscapes and towns in a car. What's more, there is the thrill of riding your bike, feeling the air against your cheeks, the ability to stop anywhere and the ambiance of adventure that comes with the nomad lifestyle.&lt;/p&gt;

&lt;p&gt;One thing I miss is a convenient method to store your trips. According to the site itself, Gmap Pedometer is &quot;A hack that uses Google's mapping application to help record distances traveled and calories burned during a running or walking workout.&quot; so one should not expect a full-fletched, shiny application but a basic user registration/login method would be handy so I could quickly access my trips. To be able to review your trips, you must store the unique url that is generated for each one in a safe place.&lt;/p&gt;

&lt;p&gt;To give you some example routes and also to store a pointer to some trips I would like to be able to access in the future I list the daily routes of two fairly recent bike routes:&lt;/p&gt;

&lt;p&gt;The Netherlands (summer 2007)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438133&quot; target=&quot;_blank&quot;&gt;Amsterdam - Den Haag&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438137&quot; target=&quot;_blank&quot;&gt;Amsterdam - Enkhuizen&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438142&quot; target=&quot;_blank&quot;&gt;Urk - Elburg&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438147&quot; target=&quot;_blank&quot;&gt;Elburg - Appeldoorn (Beekbergen)&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438149&quot; target=&quot;_blank&quot;&gt;Beekbergen - Arnhem (Oosterbeek)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Austria, going along the Danube (summer 2006)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438164&quot; target=&quot;_blank&quot;&gt;Passau - Obernzell&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438172&quot; target=&quot;_blank&quot;&gt;Obernzell - Feldkirchen&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438183&quot; target=&quot;_blank&quot;&gt;Feldkirchen - Au an der Donau&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438189&quot; target=&quot;_blank&quot;&gt;Au an der Donau - Willersbach&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438194&quot; target=&quot;_blank&quot;&gt;Willersbach - Aggsbach&lt;/a&gt;
&lt;a href=&quot;http://www.gmap-pedometer.com/?r=2438196&quot; target=&quot;_blank&quot;&gt;Aggsbach - Krems&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what are you waiting for? Hop on your bike! :)&lt;/p&gt;

&lt;p&gt;ps. Walking trips can also be recorded on the site and there is automatic route generation for walkers, too.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Ruby metaprogramming: Call counter - Take 2</title>
   <link href="http://codigoergosum.com/2008/12/15/ruby-metaprogramming-call-counter-take-2.html"/>
   <updated>2008-12-15T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/12/15/ruby-metaprogramming-call-counter-take-2</id>
   <content type="html">&lt;p&gt;So &lt;a href=&quot;http://bucionrails.com/2008/12/06/exploring-ruby-metaprogramming-call-counter/&quot; target=&quot;_blank&quot;&gt;last time&lt;/a&gt; I left you with the promise that I'd return with a solution so that the number of times a certain method was called is a class method which makes more sense than if it was an instance method. So here is the &quot;improved version&quot;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;call_counter.rb:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CallCounter&lt;/span&gt;
        
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;count_calls_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;original_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;instance_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
      &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class_variable_defined?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(:&lt;/span&gt;&lt;span class=&quot;vc&quot;&gt;@@call_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;class_variable_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(:&lt;/span&gt;&lt;span class=&quot;vc&quot;&gt;@@call_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
      &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;class_variable_get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(:&lt;/span&gt;&lt;span class=&quot;vc&quot;&gt;@@call_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
      &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bound_original_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bound_original_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;metaclass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;metaclass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instance_eval&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:calls_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nil?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:reset_counters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each_key&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;What has changed is the introduction of a class variable that counts the calls on all watched methods and that the number of calls on each method is queried by calls_to(&amp;lt;method name&amp;gt;) instead of calls_to_&amp;lt;method_name&amp;gt;. A bit less magic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;call_foo.rb:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;call_counter&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CallFoo&lt;/span&gt;
    
  &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CallCounter&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;count_calls_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;count_calls_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;(a snippet of) call_counter_spec.rb:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;call_foo&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;spec&amp;quot;&lt;/span&gt;
    
&lt;span class=&quot;n&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    
  &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:each&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@call_foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reset_counters&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        
  &lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;should be able to count several methods&amp;#39; calls&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@call_foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@call_foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I'm still not 100% content with this solution, the programming interface is nice now but it would be cool to get rid of the class variable somehow, possibly replacing it with closures. If you know how to achieve it, please leave a comment.&lt;/p&gt;

&lt;p&gt;ps. You can also get &lt;a href=&quot;http://pastie.org/338877&quot;&gt;the whole code in nice colored format&lt;/a&gt; or &lt;a href=&quot;http://pastie.org/338877.txt&quot;&gt;the raw text version&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Exploring Ruby metaprogramming: call counter</title>
   <link href="http://codigoergosum.com/2008/12/06/exploring-ruby-metaprogramming-call-counter.html"/>
   <updated>2008-12-06T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/12/06/exploring-ruby-metaprogramming-call-counter</id>
   <content type="html">&lt;p&gt;A few days ago I purchased a &lt;a href=&quot;http://www.pragprog.com/screencasts/v-dtrubyom/the-ruby-object-model-and-metaprogramming&quot;&gt;screencast by Dave Thomas on Ruby metaprogramming&lt;/a&gt;. (I do not receive any affiliation fees :)). The part I bought presents a problem and describes nine different ways of solving it in ascending order of beauty and code clarity.&lt;/p&gt;

&lt;p&gt;I was stunned by its beauty so I came up with another -though similar- problem and put together a simple solution for it. I present it for the Rubyists to silently smile in the knowledge of its elegance and power and for non-Ruby programmers to be -hopefully :)- amazed by it.&lt;/p&gt;

&lt;p&gt;The task is to count the calls to a certain method of all instances of a class.&lt;/p&gt;

&lt;p&gt;call_counter.rb:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;CallCounter&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;count_calls_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;original_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;instance_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bound_original_method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bound_original_method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;define_method&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;calls_to_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;call_counter&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;      
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;call_foo.rb:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;call_counter&amp;quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CallFoo&lt;/span&gt;
    
    &lt;span class=&quot;kp&quot;&gt;extend&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CallCounter&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;count_calls_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:foo&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;After calling &quot;count_calls_to :foo&quot; in the CallFoo class definition, calls to the &quot;foo&quot; method of CallFoo instances will be counted. A &quot;calls_to_foo&quot; method is available to get this count.&lt;/p&gt;

&lt;p&gt;I first created an UnboundMethod with &quot;instance_method&quot; and then used the bind method to attach it to an instance of ClassFoo. All this is to prevent aliasing method names, not because it is necessarily evil but because I agree with Dave Thomas about &quot;bind&quot; being a nicer solution. The define_method acts as a closure and saves its context so there is no need to use an instance variable for call_counter.&lt;/p&gt;

&lt;p&gt;You can use the counter like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;003&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#&amp;lt;CallFoo:0x608100&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;004&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls_to_foo&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;005&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;irb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;006&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls_to_foo&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Once again, what I love about Ruby is that in ~ 20 lines we have laid the base of a benchmarking tool (adding the possibility of measuring time spent in the method would not be hard). Also, the original class is not sullied by the call counting code intrinsic details. That functionality is stashed in a module, eager to be reused again.&lt;/p&gt;

&lt;p&gt;You may note there is something not quite nice about this. The method calls are counted per class, which makes sense since we usually want to know how many times the method in question was called in all instances, not per instance. However, the calls_to_foo is called on the instance which is confusing. It should be called on the class object, like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;  &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;CallFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calls_to_foo&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I may get back to this later.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>A Git guide that emboldens</title>
   <link href="http://codigoergosum.com/2008/12/04/a-git-guide-that-emboldens.html"/>
   <updated>2008-12-04T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/12/04/a-git-guide-that-emboldens</id>
   <content type="html">&lt;p&gt;Git is extremely powerful. I knew that much and that I would really like to thoroughly master it because it is so cool. However, it is quite sophisticated (not to mention that some commands, like checkout and revert designate totally different actions than in Subversion where I am coming from) and like with most things one learns by doing.&lt;/p&gt;

&lt;p&gt;One key to doing is the ability to play around with a git repository. The possibility to have an account on &lt;a href=&quot;http://github.com&quot;&gt;github.com&lt;/a&gt; and to contribute to a myriad of open source projects there removed that obstacle. The other ingredient to be a master chef is a good guide in the subject. One needs some initial self-confidence to know what he is doing lest he screws up his own work. (Note: that is very hard with git but I remember the panic when I did &quot;git checkout &amp;lt;earlier commit&amp;gt;&quot; and I did not find my earlier HEAD with &quot;git log&quot; )&lt;/p&gt;

&lt;p&gt;We may be different but I have not read a really insightful guide albeit I have gone through a dozen of them. Some are too vague or concentrate on one specific task (e.g how to create a repo on github and push to it) and some present too many options and go into details that intimidate the novice. (like the official man pages). Ladies and gentlemen, I have found it. It's the &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/user-manual.html&quot;&gt;Git User's Manual&lt;/a&gt; and it strikes the perfect balance between verbosity and shallowness. It gives examples which nicely clarify the concepts. It won't make you an expert right away, of course, but it provides you with the insight and initial courage to embark on the journey.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Installing rmagick</title>
   <link href="http://codigoergosum.com/2008/11/28/installing-rmagick.html"/>
   <updated>2008-11-28T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/11/28/installing-rmagick</id>
   <content type="html">&lt;p&gt;I needed to install rmagick for a Rails project. I had some amount of trouble along the way but finally succeeded so I am sharing my experience in case you bump into the same problems.&lt;/p&gt;

&lt;p&gt;I first installed the &lt;a href=&quot;http://imagemagick.linux-mirror.org/download/www/binary-releases.html#macosx&quot;&gt;binary OS-X distribution of imagemagick&lt;/a&gt; (no problems here) and then attempted to install rmagick, the ruby interface to the ImageMagick libraries:&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
sudo gem install rmagick
&lt;/pre&gt;


&lt;p&gt;However, I received the following unpleasant error:&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
Can't install RMagick 2.7.2. Can't find MagickCore.h.
&lt;/pre&gt;


&lt;p&gt;I checked that the header file is there (on the path the install script was looking for it), and decided not to go the hard way. After some googling I found there is a &lt;a href=&quot;http://rubyforge.org/projects/rmagick/&quot;&gt;rmagick-osx-installer&lt;/a&gt; which downloads, compiles and installs ImageMagick and rmagick. Just what I needed.&lt;/p&gt;

&lt;p&gt;However, the script failed to accomplish its mission, it hung when installing rmagick. Taking a peak in its log I saw several other errors so I had to look for another way. And that way was compiling the ImageMagick library myself. So I downloaded &lt;a href=&quot;http://imagemagick.linux-mirror.org/download/www/install-source.html#unix&quot;&gt;the source&lt;/a&gt;, made the configuration-make-make install cycle and fortunately everything went smoothly. The good news is I could install rmagick without any problem after that:&lt;/p&gt;

&lt;pre lang=&quot;shell&quot;&gt;
balint$ sudo gem install rmagick
Building native extensions.  This could take a while...
Successfully installed rmagick-2.7.2
1 gem installed
&lt;/pre&gt;

</content>
 </entry>
 
 <entry>
   <title>Refuting Rails myths</title>
   <link href="http://codigoergosum.com/2008/11/17/refuting-rails-myths.html"/>
   <updated>2008-11-17T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/11/17/refuting-rails-myths</id>
   <content type="html">&lt;p&gt;David Heinemeier Hansson, the creator of Rails is doing an &lt;a href=&quot;http://loudthinking.com/posts/29-the-rails-myths&quot;&gt;outstanding series of blog posts&lt;/a&gt; on &lt;a href=&quot;http://loudthinking.com/&quot;&gt;his blog&lt;/a&gt; to derail (pun intended) some common myths that claim Rails does not do this or that and that hinders (or rather, slows down) its widespread acceptance.&lt;/p&gt;

&lt;p&gt;I am sure David holds his best for last and will refute the infamous &quot;Rails does not scale&quot; in the final episode of the series.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>ConferenciaRails 2008: enhorabuena!</title>
   <link href="http://codigoergosum.com/2008/11/17/conferenciarails-2008-enhorabuena.html"/>
   <updated>2008-11-17T00:00:00-08:00</updated>
   <id>http://codigoergosum.com//2008/11/17/conferenciarails-2008-enhorabuena</id>
   <content type="html">&lt;p&gt;I have just returned from Madrid where the Spanish Rails Conference, &lt;a href=&quot;http://www.conferenciarails.org/&quot;&gt;Conferencia Rails&lt;/a&gt; was held. I liked it quite a lot, there were several interesting talks most of which made me want to learn all of that and very fast (one thing conferences do to me is to boost that healthy feeling of wanting to always learn and discover new things). So I would like to add my e-voice to the web noise: congratulations and thank you to the organizers and presenters!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Blackbird - simple log messages in Javascript</title>
   <link href="http://codigoergosum.com/2008/10/26/blackbird-simple-log-messages-in-javascript.html"/>
   <updated>2008-10-26T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/10/26/blackbird-simple-log-messages-in-javascript</id>
   <content type="html">&lt;p&gt;Using alert() for debugging javascript is a pain. &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1843&quot; target=&quot;_blank&quot;&gt;Firebug&lt;/a&gt; makes it a lot easier and enables several debug facilities (e.g inserting breakpoints, stepping into methods, adding variable watches) but a painless logging mechanism would still be very useful to supplement Firebug's features.&lt;/p&gt;

&lt;p&gt;Enter &lt;a title=&quot;Blackbird&quot; href=&quot;http://bucionrails.com/http://www.gscottolson.com/blackbirdjs/&quot; target=&quot;_blank&quot;&gt;Blackbird&lt;/a&gt;, a simple javascript logging tool which has a very clean, nice API and a cool console. It's really worth to check out, you can download the Blackbird files &lt;a href=&quot;http://blackbirdjs.googlecode.com/files/blackbirdjs-1.0.zip&quot; target=&quot;_self&quot;&gt;here&lt;/a&gt; and my demo &lt;a href=&quot;http://bucionrails.com/wp-content/uploads/2008/10/blackbird_trial.html&quot;&gt;here&lt;/a&gt; to try out its features. (If you use my demo, you have to save the Blackbird files in a directory named blackbirdjs that is situated in the same directory as the demo page)&lt;/p&gt;

&lt;p&gt;Blackbird's motto says it all: say &quot;hello&quot; to Blackbird and &quot;goodbye&quot; to alert().&lt;a href=&quot;http://bucionrails.com/wp-content/uploads/2008/10/blackbird_trial.html&quot;&gt;
&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>PostgreSQL pg_hba.conf authentication</title>
   <link href="http://codigoergosum.com/2008/10/22/postgresql-pg_hbaconf-authentication.html"/>
   <updated>2008-10-22T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/10/22/postgresql-pg_hbaconf-authentication</id>
   <content type="html">&lt;p&gt;I recently spent some time debugging while I can't connect to a local postgreSQL database. I wanted the nice_db database to be accessible to all local users (not real names) without any authentication. The &quot;trust&quot; authentication method was what I needed for this scenario, I was sure of this much. So I set up an authentication record in the configuration file below the one that existed by default:&lt;/p&gt;

&lt;pre lang=&quot;sql&quot;&gt;# TYPE  DATABASE    USER    CIDR-ADDRESS    METHOD
local    all          all                   ident sameuser
local    nice_db      all                   trust&lt;/pre&gt;


&lt;p&gt;But this gave me the following error and denied access:&lt;/p&gt;

&lt;p&gt;psql: FATAL:  Ident authentication failed for user &quot;balint&quot;&lt;/p&gt;

&lt;p&gt;I tried several things making the second record more allowing each time (in fact, what you see above is the final, most liberal version) to no avail. I then swapped the order of the two records and finally was granted access.&lt;/p&gt;

&lt;p&gt;Of course, I should have been wiser and apply the grand old &lt;acronym title=&quot;Read The Fucking Manual&quot;&gt;RTFM&lt;/acronym&gt; principle. The &lt;a title=&quot;PostgreSQL documentation&quot; href=&quot;http://www.postgresql.org/docs/7.4/static/client-authentication.html&quot; target=&quot;_blank&quot;&gt;PostgreSQL documentation&lt;/a&gt; states in very clear terms how each line in the pg_hba.conf is accessed:&lt;/p&gt;

&lt;blockquote&gt;The first record with a matching connection type, client address, requested database, and user name is used to perform authentication. There is no &lt;span class=&quot;QUOTE&quot;&gt;&quot;fall-through&quot;&lt;/span&gt; or    &lt;span class=&quot;QUOTE&quot;&gt;&quot;backup&quot;&lt;/span&gt;: if one record is chosen and the authentication fails, subsequent records are not considered. If no record matches, access is denied.&lt;/blockquote&gt;


&lt;p&gt;For my particular case, the &quot;local all all ident sameuser&quot; record blocked access to all databases but to those whose name matched that of the operating system's user (that's what the ident sameuser does) since that matches all user and database names.&lt;/p&gt;

&lt;p&gt;Beyond the mechanics of PostgreSQL authentication (put the authentication records that match more users/databases below the ones that are more specific), I have learned something which is more precious and that I can put into good use in the future: RTFM!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>javascript method chain</title>
   <link href="http://codigoergosum.com/2008/10/09/javascript-method-chain.html"/>
   <updated>2008-10-09T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/10/09/javascript-method-chain</id>
   <content type="html">&lt;p&gt;John Resig has an extraordinary advanced javascript tutorial on his &lt;a href=&quot;http://ejohn.org/apps/learn/&quot; target=&quot;_blank&quot;&gt;blog&lt;/a&gt; that he presented on &lt;a href=&quot;http://en.oreilly.com/webexny2008/public/content/home&quot; target=&quot;_blank&quot;&gt;a web conference&lt;/a&gt;. It is definitely worth a walk-through since it expands one's javascript horizon unless one has not written a javascript framework himself.&lt;/p&gt;

&lt;p&gt;I played around with several of his slides learning a lot. My favorite was probably &lt;a href=&quot;http://ejohn.org/apps/learn/#90&quot;&gt;the last slide&lt;/a&gt; which explains how method overloading works using the fact that &lt;em&gt;methodname&lt;/em&gt;.length in javascript gives back the number of expected arguments of that function.&lt;/p&gt;

&lt;pre lang=&quot;javascript&quot;&gt;
function addMethod(object, name, fn){ 
  // Save a reference to the old method 
  var old = object[ name ];
 
  // Overwrite the method with our new one 
  object[ name ] = function(){ 
    // Check the number of incoming arguments, 
    // compared to our overloaded function 
    if ( fn.length == arguments.length ) 
      // If there was a match, run the function 
      return fn.apply( this, arguments ); 
 
    // Otherwise, fallback to the old method 
    else if ( typeof old === &quot;function&quot; ) 
      return old.apply( this, arguments ); 
  }; 
} 
 
function Ninjas(){ 
  var ninjas = [ &quot;Dean Edwards&quot;, &quot;Sam Stephenson&quot;, &quot;Alex Russell&quot; ]; 
  addMethod(this, &quot;find&quot;, function(){ 
    return ninjas; 
  }); 
  addMethod(this, &quot;find&quot;, function(name){ 
    var ret = []; 
    for ( var i = 0; i &lt; ninjas.length; i++ ) 
      if ( ninjas[i].indexOf(name) == 0 ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
  addMethod(this, &quot;find&quot;, function(first, last){ 
    var ret = []; 
    for ( var i = 0; i &lt; ninjas.length; i++ ) 
      if ( ninjas[i] == (first + &quot; &quot; + last) ) 
        ret.push( ninjas[i] ); 
    return ret; 
  }); 
} 
 
var ninjas = new Ninjas(); 
assert( ninjas.find().length == 3, &quot;Finds all ninjas&quot; ); 
assert( ninjas.find(&quot;Sam&quot;).length == 1, &quot;Finds ninjas by first name&quot; ); 
assert( ninjas.find(&quot;Dean&quot;, &quot;Edwards&quot;).length == 1, &quot;Finds ninjas by first and last name&quot; ); 
assert( ninjas.find(&quot;Alex&quot;, &quot;X&quot;, &quot;Russell&quot;) == null, &quot;Does nothing&quot; );
&lt;/pre&gt;


&lt;p&gt;It took me some time to figure out how exactly the method calls are routed but it was an interesting process nevertheless. I guess the one tricky part to interpret is the following bit:&lt;/p&gt;

&lt;pre lang=&quot;javascript&quot;&gt;
if ( fn.length == arguments.length ) 
  // If there was a match, run the function 
  return fn.apply( this, arguments ); 
 
  // Otherwise, fallback to the old method 
  else if ( typeof old === &quot;function&quot; ) 
    return old.apply( this, arguments ); 
  }; 
&lt;/pre&gt;


&lt;p&gt;This makes a method chain and allows for method overloading. With the three addMethod calls in the above example a chained method is built up.&lt;/p&gt;

&lt;p&gt;After the call to addMethod with no arguments (the first one), the find method of the Ninjas &quot;class&quot; will return all ninjas if called with no arguments and do nothing if called with any number of arguments. After the call to addMethod with one single name argument the find method will return the ninjas whose first name matches the passed argument if there is only one argument, return all ninjas if it has been called with no arguments and do nothing otherwise.&lt;/p&gt;

&lt;p&gt;I could go on but the pattern is probably clear now. At each call of the find method, the lastly added method is matched for the number of arguments (so in the above example, it will match if the caller passed two arguments) and the method called if the match is successful. Otherwise, it will try to match the number of arguments with the method that was added before the last one, and so on.&lt;/p&gt;

&lt;p&gt;I am elaborating this in so much detail because&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;it was such a &quot;Eureka!&quot; moment for me when I got it. &lt;/li&gt;
    &lt;li&gt;it is an incredibly ingenious way to flex the possibilites of javascript and introduce an OOP concept into an originally non-OOP language.&lt;/li&gt;

&lt;/ol&gt;


&lt;p&gt;I think John Resig made javascript lovable again which is why he deserves my total gratitude.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>My first DSL in Ruby</title>
   <link href="http://codigoergosum.com/2008/09/21/my-first-dsl-in-ruby.html"/>
   <updated>2008-09-21T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/09/21/my-first-dsl-in-ruby</id>
   <content type="html">&lt;p&gt;I read a &lt;a href=&quot;http://www.artima.com/rubycs/articles/ruby_as_dsl.html&quot;&gt;few&lt;/a&gt; &lt;a href=&quot;http://www.artima.com/rubycs/articles/ruby_as_dsl.html&quot;&gt;posts&lt;/a&gt; about how good fit Ruby is for building DSLs, Domain Specific Languages. Ever the curious I have been waiting for the opportunity to build a very simple one for a particular problem.&lt;/p&gt;

&lt;p&gt;Well, I did not have to wait very long (when you have a hammer everything looks like a nail). I needed a quick method which generates nice html graphs for &lt;a href=&quot;http://bucionrails.com/2008/09/17/v8-javascript-engine-benchmarks/&quot;&gt;my post about browser javascript engine benchmarking&lt;/a&gt;. After spending a few minutes searching for a free tool (I did not want anything fluffy, just something very basic) I hit the nail in the head with my hammer. Only the nail was the generated HTML charts for my post and the hammer, (my desire to build) a DSL in Ruby.&lt;/p&gt;

&lt;p&gt;I would like to say it was difficult but in fact it was a piece of cake with Ruby (and armed with the knowledge of previous DSL builders). The solution is composed of the following three parts:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;The DSL file which defines the charts&lt;/li&gt;
    &lt;li&gt;The interpreter which understands the definitions in the DSL file&lt;/li&gt;
    &lt;li&gt;The &quot;controller&quot; which just passes the data contained in the DSL file to the interpreter&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;So let's see each part separately:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;browser_js_benchmarks.dsl (the DSL)&lt;/strong&gt;&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
chart &quot;Score&quot; do |c|
    c.add &quot;Safari 3.1.2&quot; =&gt; 164
    c.add &quot;Firefox 3.0.1&quot; =&gt; 156
    c.add &quot;Shiretoko&quot; =&gt; 145
    c.add &quot;Google Chrome&quot; =&gt; 1589
end
&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;chart.rb (the interpreter)&lt;/strong&gt;&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
require &quot;math_aux&quot;

class ChartDSL
    
    Template = %(&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;%%CAPTION%%&lt;/caption&gt;%%ITEMS%%&lt;/table&gt;)
    Background_colors = %w(red blue green yellow grey)
    
    attr_reader :values
    def initialize
        @charts = Array.new
        @values = Hash.new
    end
    
    def chart(name)     
        @name = name
        yield self
        @charts.push(make_html)
    end
    
    def add(name_and_value)
        @values ||= Hash.new
        @values.merge!(name_and_value)
    end
    
    def load(filename)
        # c = new
        instance_eval(File.read(filename), filename)
        write_output
    end

    def make_html
        sorted_pairs = @values.sort_by { |v| - v[1] }
        vals = sorted_pairs.map { |p| p[1] }
        norm_values = MathAux::normalize(vals, 100.0)
        html = Array.new
        sorted_pairs.each_with_index do |pair, i|
            name, value = pair
            html.push(%Q(&lt;tr&gt;&lt;td&gt;#{name}&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:#{norm_values[i]}px;background-color:#{ChartDSL::Background_colors[i]}&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;#{value}&lt;/td&gt;&lt;/tr&gt;))
        end
        filled_chart = ChartDSL::Template.sub(&quot;%%CAPTION%%&quot;, @name)     
        filled_chart.sub(&quot;%%ITEMS%%&quot;, html.join)
    end
    
    def write_output
        File.open(&quot;generated_charts.html&quot;, &quot;w&quot;) do |f|
            f.write(@charts)
        end
    end
end

&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;chart_loader.rb (the controller)&lt;/strong&gt;&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
require &quot;chart&quot;
class ChartLoader
    def self.load_chart(dsl_filename)
        c = ChartDSL.new
        c.load(dsl_filename)
    end
end

if __FILE__ == $0
    ChartLoader.load_chart(ARGV[0])
end
&lt;/pre&gt;


&lt;p&gt;For the sake of completeness here is &lt;strong&gt;math_aux.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
module MathAux
    def self.normalize(numbers, to=1.0)
        norm_rat = to / numbers.max
        numbers.map { |n| n * norm_rat }
    end
end
&lt;/pre&gt;


&lt;p&gt;To generate the charts, one only has to run &quot;the interpreter&quot; with a dsl file as the first parameter:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
ruby chart_loader.rb browser_js_benchmarks.dsl
&lt;/pre&gt;


&lt;p&gt;The output is called generated_charts.html and contains the following:&lt;/p&gt;

&lt;pre lang=&quot;xml&quot;&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;
&lt;caption&gt;Score&lt;/caption&gt;
 &lt;tr&gt;
  &lt;td&gt;Google Chrome&lt;/td&gt;
  &lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
  &lt;td&gt;1589&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Safari 3.1.2&lt;/td&gt;
  &lt;td&gt;&lt;div style=&quot;width:10.3209565764632px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&lt;/td&gt;  &lt;td&gt;164&lt;/td&gt;&lt;/tr&gt;
 &lt;tr&gt;
  &lt;td&gt;Firefox 3.0.1&lt;/td&gt;
  &lt;td&gt;&lt;div style=&quot;width:9.81749528005034px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&lt;/td&gt; &lt;td&gt;156&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
 &lt;td&gt;Shiretoko&lt;/td&gt;
 &lt;td&gt;&lt;div style=&quot;width:9.12523599748269px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&lt;/td&gt;&lt;td&gt;145&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/pre&gt;


&lt;p&gt;Note that in ~30-40 code lines we have a &quot;language interpreter&quot;, one that understands the chart DSL and spits out some HTML code that represents the charts. Of course there is plenty of room for improvement, like having the same color denote the same actor between charts (Firefox 3.0.1 should always be the blue bar, for example, unlike in &lt;a href=&quot;http://bucionrails.com/2008/09/17/v8-javascript-engine-benchmarks/&quot;&gt;my post&lt;/a&gt;), using a better solution for the template strings, adding the possibility of pie charts (although &quot;standard&quot; HTML is not very flexible on different chart forms, one would probably have to use a &lt;a href=&quot;http://developer.mozilla.org/en/Canvas_tutorial&quot;&gt;&amp;lt;canvas&amp;gt; &lt;/a&gt;), and so on.&lt;/p&gt;

&lt;p&gt;The essential thing is that it works and it does what the particular situation demanded. It took me a couple of interrupted hours plus the time to read through two related posts which is not that much given that I now have a &quot;tool&quot; (once again, I feel a bit conceited to call it that) which I can use for my future posts whenever the need arises. A custom hammer for my custom nail.&lt;/p&gt;

&lt;p&gt;(If you care, feel free to download, use and modify the source code located &lt;a href=&quot;http://github.com/balinterdi/chart-maker-dsl/tree/master&quot;&gt;here&lt;/a&gt;)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>V8 javascript engine benchmarks</title>
   <link href="http://codigoergosum.com/2008/09/17/v8-javascript-engine-benchmarks.html"/>
   <updated>2008-09-17T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/09/17/v8-javascript-engine-benchmarks</id>
   <content type="html">&lt;p&gt;A few weeks back when I read about &lt;a href=&quot;http://www.google.com/googlebooks/chrome&quot;&gt;Chrome&lt;/a&gt; I became interested in V8, a javascript engine that Google integrated in their browser and that they claimed to be very fast due to the following reasons:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;strong&gt;Hidden class transitions&lt;/strong&gt; that enable dynamic optimizations since objects will use the same (hidden) class&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;generating machine code&lt;/strong&gt; instead of interpreting the source code each time&lt;/li&gt;
    &lt;li&gt;&lt;strong&gt;incremental garbage collection&lt;/strong&gt; which reduces the time needed for the cleanup to milliseconds and eliminates &quot;second long pauses&quot;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;All that sounded very promising but as an engineer by profession it left me with a desire to find out how much faster all these features made V8 (and any browser that might use it). Even more so since I love running benchmarks and compare numbers. Well, maybe Google sensed that since they provided all the necessary tools to run these tests on the &lt;a href=&quot;http://code.google.com/apis/v8/benchmarks.html&quot;&gt;V8 benchmark page&lt;/a&gt; and to run them very easily.&lt;/p&gt;

&lt;p&gt;There are 5 different algorithms in the testing suite exercising different qualities of the javascript engine. To be fair I closed all other tabs in browsers during the testing attempting to minimize operations that can have an effect on test performance. Also, the V8 tests were run from the command line so that might skew the results a bit towards V8. Anyyway, here are the results (numbers mean execution time so smaller is better):&lt;/p&gt;

&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;Richards&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;2072&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:7.33590733590734px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;152&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:5.5984555984556px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;116&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:4.39189189189189px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;91&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;DeltaBlue&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;1753&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:9.75470621791215px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;171&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:7.24472333143183px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;127&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:7.01654306902453px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;123&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;Crypto&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;1415&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:10.6007067137809px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:10.6007067137809px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;150&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:9.54063604240283px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;135&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;RayTrace&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;1021&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:22.7228207639569px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;232&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:12.3408423114594px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;126&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:11.1655239960823px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;114&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;EarleyBoyer&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;1933&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:16.9684428349715px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;328&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:13.3988618727367px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;259&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:9.72581479565442px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;188&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;table border=&quot;0&quot; cellspacing=&quot;5&quot; cellpadding=&quot;5&quot;&gt;&lt;caption&gt;Score&lt;/caption&gt;&lt;tr&gt;&lt;td&gt;Google Chrome&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:100.0px;background-color:red&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;1589&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Safari 3.1.2&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:10.3209565764632px;background-color:blue&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;164&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Firefox 3.0.1&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:9.81749528005034px;background-color:green&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;156&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shiretoko&lt;/td&gt;&lt;td&gt;&lt;div style=&quot;width:9.12523599748269px;background-color:yellow&quot;&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;&lt;td&gt;145&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;p&gt;The superiority of V8 stunned me so much even to push me to ask whether all this is possible. Googe Chrome that uses V8 is on average (see Score) 10 times faster than all the other browsers (that pretty much flock together). I expected to find the speed of Firefox 3.1 (codename Shiretoko) close to that of Chrome but to my surprise it does not even surpass that of the other browsers. That made me a bit disappointed since I am a big Firefox fan.&lt;/p&gt;

&lt;p&gt;Can it be that these benchmarks are somehow tailored to show V8's dominance? (like some political polls are skewed to give the &quot;correct&quot; answer). That this is not such a far-fetched idea is supported by Mozilla's announcement that TraceMonkey, &lt;a href=&quot;http://www.techcrunch.com/2008/09/03/mozilla-fights-back-with-new-firefox-benchmarks/&quot;&gt;Firefox's javascript engine will be 16-28% faster than V8&lt;/a&gt;. And they have their own benchmarking solution, SunSpider to prove their point.&lt;/p&gt;

&lt;p&gt;So the life of javascript engine developers has got a lot harder. Not only they have to implement a fast engine but also a benchmarking system that shows there is nothing as fast as theirs!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Navigator for the Google Chrome comicbook</title>
   <link href="http://codigoergosum.com/2008/09/03/navigator-for-the-google-chrome-comicbook.html"/>
   <updated>2008-09-03T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/09/03/navigator-for-the-google-chrome-comicbook</id>
   <content type="html">&lt;p&gt;The first beta version (for now only for Windows) of &lt;a href=&quot;http://googleblog.blogspot.com/2008/09/fresh-take-on-browser.html&quot;&gt;Google's browser is out, &lt;/a&gt;but I don't think Google needs the marketing power of my post so that's not what I want to talk about. The browser is introduced by a &lt;a href=&quot;http://www.google.com/googlebooks/chrome/&quot;&gt;ingenious comics&lt;/a&gt; of 39 pages. However, the navigator is too simple, in my opinion in that you cannot skip a page so if you read until say page 19 and you have to start over (e.g you closed the browser), you have to click on the &quot;Next&quot; link 18 times. There is no unique URL for each page, the whole navigation is done with a javascript snippet changing the image (the cartoon strip) when the user clicks &quot;Prev&quot; or &quot;Next&quot;.&lt;/p&gt;

&lt;p&gt;So I took a peep at the source of the page and reverse-engineered the navigation which is simply a javascript call to goPage('next') when the user clicks the Next link. So now I can simply write&lt;/p&gt;

&lt;pre lang=&quot;javascript&quot;&gt;
javascript:for (var i=0; i &lt; 10; i++) goPage('next');&lt;/pre&gt;


&lt;p&gt;to the location bar to skip 10 pages ahead and do the same with 'prev' to rewind 10 pages.&lt;/p&gt;

&lt;p&gt;I know &quot;reverse-engineering&quot; is way too conceited a term for this but this kind of hacking tickles my brain in a very joyful way and feels a bit like outsmarting Google. And that's not bad at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; I now realize the comics's navigation has been redesigned so my above fix became obsolete. At least I cherish the knowledge my hack addressed a real UI problem (and did that faster than Google :) ).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Now that's what I call Web2.0: Ubiquity</title>
   <link href="http://codigoergosum.com/2008/08/29/now-thats-what-i-call-web20-ubiquity.html"/>
   <updated>2008-08-29T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/08/29/now-thats-what-i-call-web20-ubiquity</id>
   <content type="html">&lt;p&gt;I've stumbled upon a great Firefox plugin, Ubiquity. It basically accesses several web services (GoogleMaps, Gmail, Flickr, etc.) via its own panel and with its own commands so that common online tasks (e.g looking up something on Wikipedia you have just found on a page) become amazingly simple. I was really stunned by how much this plugin is capable of doing after watching the &lt;a href=&quot;http://vimeo.com/1561578?pg=embed&amp;amp;sec=1561578&quot; target=&quot;_blank&quot;&gt;briefing video&lt;/a&gt; and going through the &lt;a href=&quot;https://wiki.mozilla.org/Labs/Ubiquity/Ubiquity_0.1_User_Tutorial&quot; target=&quot;_blank&quot;&gt;tutorial&lt;/a&gt;. And that does not stop there: power users can add their own commands to extend the already vast capabilities of the plugin. It's been a long time I've been so excited about a &quot;web 2.0&quot; tool.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.azarask.in/blog/&quot; target=&quot;_blank&quot;&gt;Here&lt;/a&gt; is the blog post about Ubiquity on Aza Raskin's blog who is the main developer of the plugin.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: If you use a Mac, you'll need &lt;a href=&quot;http://growl.info/about.php&quot; target=&quot;_blank&quot;&gt;Growl&lt;/a&gt; for Ubiquity to display its command panel.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Can less work be more?</title>
   <link href="http://codigoergosum.com/2008/07/17/can-less-work-be-more.html"/>
   <updated>2008-07-17T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/07/17/can-less-work-be-more</id>
   <content type="html">&lt;p&gt;I saw the &lt;a href=&quot;http://onrails.org/articles/2008/05/31/railsconf-2008-david-heinemeier-hanssons-keynote-video&quot;&gt;keynote speech David Heinemeier Hansson&lt;/a&gt; gave at this year's Railsconf in Portland and I liked it a lot. I really like the idea of following the pattern of &quot;Less software is more&quot; to the work we do each day. In his speech he says developers should spend one day a week discovering a subject of interest, writing code for a pet project, contributing to an open source project, etc. Basically anything but doing the work they do on the other four days of the week. This &quot;day-off&quot; raises the developer's productivity so it is a net gain for the main work he is involved with, too.&lt;/p&gt;

&lt;p&gt;I tend to agree. However, in this post I want to elaborate rather what 'be more' means in both the 'less software is more' and the 'less work is more' phrases. Less software means less lines of code to achieve the same tasks. Less work means less time spent working producing code to achieve the same tasks. There are two underlying concepts here that make this possible: abstraction and productivity. More precisely: the  ideas in your (hacker) head and the tools that allow you to implement these ideas in abstract, high-level  terms and thus raise your productivity.&lt;/p&gt;

&lt;p&gt;When you write a program, there are basically two phases of producing code that solves a problem: first, you think about how to solve it and second, you convert the ideas into code. There is always a gap between the ideas and the code you write and that the computer comprehends. The more high-level the language is, the smaller the gap that needs to be bridged. But there is a backward effect, too. Usually when you are in the first phase you already think in terms of the second. The expressive tools the language provides have a strong effect on how you think of the problem (generally you know what language your solution will be implemented in). And that is bad because it dumbs down your thinking before you get to the point where you should consider the possibilities of the language.&lt;/p&gt;

&lt;p&gt;I tend to think less of the language specifics in the first phase if I know the language provides all the high-level tools and provides them neatly. &quot;For&quot; loops skews your thinking more than -all kinds of- iterators. If I know functions are first-class objects and metaprogramming is available I worry less about how (or whether!) my abstract solution, only existing on the plane of ideas can be converted to functioning code.&lt;/p&gt;

&lt;p&gt;So, back to where I started, your choice of the language counts and it counts a lot. It can help you be more productive in several ways, not just the fewer-lines-of-code-to-do-the-same-thing way but also the minimizing-the-skewing-of-your-thinking way. However, a high-level language is no guarantee to achieve that. One can churn out C-like code in Ruby, it is just easier to realize you are not using the full arsenal. And that's where it really kicks in: if you know you can basically do anything painlessly you will dare to think big, your ideas can get off the ground. Consequently they will be abstract enough for you to be more productive.&lt;/p&gt;

&lt;p&gt;So armed with daringly abstract ideas and tools that make it possible to put them into code, one sets out to conquer the world. The limit to the amount of code generated is the number of hours one can spend each day programming. After about ~8 hours of work is it worth to put in some more time to produce more code? &lt;a href=&quot;http://www.extremeprogramming.org/rules/overtime.html&quot;&gt;Probably not&lt;/a&gt;. Our thinking breaks down pretty fast after that. I have experienced on several occasions that I could do in 10 minutes the next morning what I could not do in 2 hours the evening before. This is not about dropping the keyboard when the clock strikes 5pm, of course. It is about &lt;a href=&quot;http://www.extremeprogramming.org/rules/velocity.html&quot;&gt;planning for measurable progress without too much overtime&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think David is right when asserting that replenishing your mind so it can come up with constructive ideas is equally important. I am sure there are numerous ways to attain that. Some of them are constructive activities in themselves (David's example was playing the banjo), some may just give you peace (e.g friends, family) and some may simply drift your thoughts away from the very problem you are working on (e.g playing soccer) and help you that way.&lt;/p&gt;

&lt;p&gt;So what do you think about all that? Can low-level languages still have advantages over high-level ones in certain situations? Do you think the language your are programming in can have an effect on your problem-solving thoughts? What activities switch you off in the most &quot;productive&quot; way? What other factors have an effect on your work? (of course your working environment is very relevant). Are &lt;a href=&quot;http://www.boston.com/bostonglobe/ideas/naps/&quot;&gt;naps &lt;/a&gt;worth it? When would the official Railsconf'08 videos be online? :)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>First Mexperiences</title>
   <link href="http://codigoergosum.com/2008/05/27/first-mac-experiences.html"/>
   <updated>2008-05-27T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/05/27/first-mac-experiences</id>
   <content type="html">&lt;p&gt;I recently wrote &lt;a href=&quot;http://bucionrails.com/2008/05/22/confession-of-a-conversion/&quot;&gt;about me getting a Mac&lt;/a&gt;, the reasons I made the switch and how I really like it. I would now like to add nuances to this overall picture. What is really cool? What is hard to get used to? Which are the things I could not find how to achieve on the Mac?&lt;/p&gt;

&lt;h3&gt;Non-keyboard input&lt;/h3&gt;


&lt;p&gt;I think I am one of the few who prefers the trackball (Thinkpad-style) to trackpads. For me, trackpads are clumsy, it is hard to position the cursor correctly, they make an incomfortable sound and I often click inadvertently by pushing too hard (but not hard at all). So I had thought I'd get a mouse but then I found out the usb ports are located on the left hand side of the Macbook which does not seem to logical unless Apple specifically targeted left-handed people. Or does everyone already have cordless mice?&lt;/p&gt;

&lt;p&gt;Anyway, I gave the trackpad a try and I was thoroughly satisfied. The trademark two-finger scrolling works miracle, clicking is silent and the trackpad is wide enough to be able to lay two-fingers on the pad and click with my thumb which serves as a right-click. Absolutely phenomenal. My plans to acquire a cordless mouse have been postponed. (Even more so since I learned from a colleague that to really get the best out of the mouse you need to &lt;em&gt;purchase&lt;/em&gt; a driver. I can imagine paying for software, but for a mouse driver? that seems harsh.)&lt;/p&gt;

&lt;h3&gt;Managing windows and menus&lt;/h3&gt;


&lt;p&gt;Having said all about non-keyboard input I always try to minimize the time I have to lift my hands from the keyboard in all applications. Switching between applications is easy with cmd+tab and I also learned the cmd+` and cmd+~ which switches between windows of the same application and is very useful. Closing an application with cmd+q and a tab/window with cmd+w also come in handy and was easy to learn. However, one thing which I miss badly is a key combination to just go to the menu and browse there (e.g alt+f1 in gnome). I mean there are several combinations to activate certain menu items but if I do not want to learn a few dozens of them per application it seems a good idea to me to have just one and then be able to access everything. Or maybe there is, waiting for me to discover it.&lt;/p&gt;

&lt;h3&gt;Command line boosters&lt;/h3&gt;


&lt;p&gt;Another feature I adore in the terminal is to be able to quickly navigate. Go to the start, to the end, skip a word forwards, backwards, delete a word, etc. One extra advantage of my favorite text editor, emacs, is that its combinations coincide with those used on the command line, which is fantastic. After a while, I learned that they can all be invoked in Mac terminals, too, it is just that they seem less logical too me. For example , Esc-D is to delete from the cursor to the end of the word, why is Ctrl-W Delete the word to the left of the cursor? (found &lt;a href=&quot;http://ie.brokethe.net/2008/2/6/mac-terminal-shortcuts&quot;&gt;here&lt;/a&gt;). Also, Esc is too far away to reach comfortably. I know iTerm can be programmed to respond to any key combination, so I might do some tinkering here to have a more consistent interface.&lt;/p&gt;

&lt;h3&gt;Installing software&lt;/h3&gt;


&lt;p&gt;Getting applications installed on your computer is quite easy with the disk image installers or one can always compile from source the advantages of which are described &lt;a href=&quot;http://hivelogic.com/articles/2005/11/using_usr_local&quot;&gt;in this excellent article&lt;/a&gt;. I have to tell that the provided applications are really top notch like iTunes or iPhoto, and I haven't even had the time to try all of them (iMovie, Garage Band, etc.). One caveat is that some applications, like iPhoto treats your data as one big library file so you need to export particular files if you need them outside of the application (how do you upload individual photos to a photo company's site to have them developed? how do you upload an image to a photo-sharing website? you'll need plugins or you have to export them thus duplicating the photos and wasting space). This surely suits ordinary users but advanced, tech-savvy users don't like this kind of obfuscation, or at least I don't.&lt;/p&gt;

&lt;p&gt;A big pain for me is the presence of spaces in directory names. It may be an old habit to automatically evade them but it looks amateurish to me. Which Mac (and OS/X) is certainly not. It is a great machine (and operating system) to have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Post scriptum.&lt;/strong&gt; I am most interested to see what &lt;a href=&quot;http://www.fernandoguillen.info/es/blog/2008/05/23/dios-mio-que-he-hecho/&quot;&gt;Fernando&lt;/a&gt; has to say about his first steps with his Mac.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt; I realized the iPhoto Library file does contain the actual photos although in a shrunk version. You can't see this in the Finder, you have to use the command line (which is ok since that can be considered as a habit that distinguishes a normal user from a power user). To be able to burn the photos to a DVD or upload them somewhere, you still have to export them and thus have your photos duplicated (even if only for the time of creating the CD/uploading the photos).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Confession of a conversion</title>
   <link href="http://codigoergosum.com/2008/05/22/confession-of-a-conversion.html"/>
   <updated>2008-05-22T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/05/22/confession-of-a-conversion</id>
   <content type="html">&lt;p&gt;My company laptop has gotten old and weary. So old that I could not even find a replacement battery and some memory for it. I could, but for half a price of a shiny new notebook that is three times stronger. I liked my old laptop, but not that much. So I went looking for a new one. I was hesitating between a Thinkpad and an ASUS since I was pretty content with both of them but the faint voice was already whispering into my ear: &quot;get a Mac, get a Mac&quot;.&lt;/p&gt;

&lt;p&gt;I'll admit the sysadmin side of things is not my favorite part of working with a computer. I have nothing against modifying configuration files, installing software from the command line and the like but I do feel like I am wasting my time when trying to get Skype voice to work for several hours to no avail, make my laptop &quot;soft-hibernate&quot; when I close the lid (I got that one, finally) or set up the wifi hotspot selector icon. I know it is just a matter of time and perseverance and I like the idea that you can get it to work if you finally understand what needs to be tweaked and how. (In fact, most of the time you don't. You just find the answer by searching on Google, copy-paste something you don't understand and eureka, it works.). It is just that my priorities lie elsewhere. It has been said a million times but it is still true: time is too precious to spend on anything but the most important things. For me, these are writing code, learning software, discovering new tools and technologies.&lt;/p&gt;

&lt;p&gt;There was something more in favor of a Mac: its design. I don't primarily mean the physical design of the laptop though in my opinion it is the &lt;a href=&quot;hhttp://www.apple.com/macbook/design.html&quot;&gt;best looking one&lt;/a&gt; there is but how everything works so ingeniously and smoothly. Everything is pre-installed so I basically only had to customize a few things like creating a user (it took me a while to realize who the guy on the default avatar picture was since I was not moving too much), setting the time zone and the default keyboard layout, etc. And the fonts. Yes, the fonts above all. I remember how refreshing it was when I switched to a Gnome desktop from Windows XP several years ago. I felt the same but even stronger when I opened Firefox the first time on my new Mac. My heart is filled with joy using iTerm with the &lt;a href=&quot;http://www.myfonts.com/fonts/apple/monaco/&quot;&gt;Monaco font&lt;/a&gt;. I know font types and the look of fonts should probably be a detail for stone-hearted programmers but on the other hand beauty in details is so important. I spent some time thinking whether using nicer terminal fonts makes me a happier developer and it certainly does. I could do without the whizzing windows, sliding workspaces and flamboyant icons but I can not imagine using anything with less beautiful fonts. In three weeks I have become so fond of my precious little fonts I have a hard time imagining abandoning them.&lt;/p&gt;

&lt;p&gt;But it is just me. What about you? What made you change to a Mac? What do you fancy most about it? Or if you are not a Mac owner, what do you like most about your Linux/Windows/etc. machine?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Agile help with Rails</title>
   <link href="http://codigoergosum.com/2008/04/21/agile-help-with-rails.html"/>
   <updated>2008-04-21T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/04/21/agile-help-with-rails</id>
   <content type="html">&lt;p&gt;I have recently taken the habit of checking on &lt;a href=&quot;http://railsforum.com&quot;&gt;Rails forum&lt;/a&gt; from time to time whether there are unanswered questions I can help with. The best way to see a problem in its context is to recreate it and I was amazed by how easy it is to set up a rails site and debug e.g &lt;a href=&quot;http://railsforum.com/viewtopic.php?id=17529&quot;&gt;a routing problem&lt;/a&gt;.&lt;/p&gt;

&lt;div style=&quot;margin-top:20px;margin-bottom:20px&quot;&gt;
&lt;code&gt;
&gt; rails railsforum_help_routing
&gt; createdb railsforum_help_routing_development
(edit database.yml to set user and possibly database type)
&gt; script/generate model Trip
&gt; script/generate controller Trip
(edit routes.rb, in this case)
&lt;/code&gt;
&lt;/div&gt;


&lt;p&gt;Naturally the fact that all this takes about 5 minutes greatly leverages lending a hand to a fellow developer. Now that's what I call agile!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Code syntax highlighting</title>
   <link href="http://codigoergosum.com/2008/04/12/code-syntax-highlighting.html"/>
   <updated>2008-04-12T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/04/12/code-syntax-highlighting</id>
   <content type="html">&lt;p&gt;I realized this would be a key feature of any blog that aims to include code snippets in posts right after my friend, Bronson, told me so. With Wordpress, it seems, the problem is not that there are no tools for a certain task but that there are too many. Anyway, I finally found &lt;a href=&quot;http://wordpress.org/extend/plugins/wp-syntax/&quot;&gt;this one&lt;/a&gt; to perfectly suit my needs. It supports a plethora of programming/markup languages and the only thing you should add to your code blocks, is a lang attribute to the &amp;lt;pre&amp;gt; like so:&lt;/p&gt;

&lt;pre lang=&quot;html4strict&quot;&gt;
   &lt;pre lang=&quot;ruby&quot;&gt;
    (ruby code comes here)
   &lt;/pre &gt;
&lt;/pre&gt;


&lt;p&gt;My code  in &lt;a href=&quot;http://bucionrails.com/2008/04/09/quick-adaptor-my-role-model/&quot;&gt;my earlier post&lt;/a&gt; looks a lot better, doesn't it?&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Quick adaptor - my role model</title>
   <link href="http://codigoergosum.com/2008/04/09/quick-adaptor-my-role-model.html"/>
   <updated>2008-04-09T00:00:00-07:00</updated>
   <id>http://codigoergosum.com//2008/04/09/quick-adaptor-my-role-model</id>
   <content type="html">&lt;p&gt;I returned two weeks ago from the fantastic &lt;a href=&quot;http://www.euruko2008.org/&quot;&gt;Euruko 2008 conference&lt;/a&gt; in Prague dazzled by the outstanding presentations and the power of Ruby. It is hard to pick a favorite but I especially liked David Black's &quot;Per-Object Behavior in Ruby&quot; (slides hopefully coming up) mainly because I am a sucker for metaprogramming and the true object-orientedness of Ruby in all its glory.&lt;/p&gt;

&lt;p&gt;One fundamental concept was the singleton class which I think I've finally understood from this session. His example was the OpenStruct class whose instances learn to respond to all messages sent to them (this is Smalltalk/Ruby parlance, we could also say they learn to handle method calls) instead of throwing a NoMethodError. So I thought a great way to gain an insight of how this works is to actually code that up myself. Here is what I got:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
require 'test/unit'
class QuickAdaptor
  def method_missing(method_id, *args)
    method_name = method_id.to_s
    if method_name =~ /=$/
      attr = method_name.to_s.chop
      self.class.class_eval do
        define_method method_id do |x|
          instance_variable_set(&quot;@#{attr}&quot;, x)
        end
        method_name.chop!
        define_method method_name.to_sym do
          instance_variable_get &quot;@#{attr}&quot;
        end
      end
      instance_variable_set(&quot;@#{attr}&quot;, args[0])
    end
  end

end

class QuickSingletonAdaptor
  # does the same as QuickAdaptor
  # but only defines methods for singleton
  # class of object, so it is not the class
  # that &quot;learns&quot;, but the singleton class
  def method_missing(method_id, *args)
    method_name = method_id.to_s
    if method_name =~ /=$/
      attr = method_name.to_s.chop
      singleton_class = class &lt;&lt; self ; self; end
      singleton_class.instance_eval do
        define_method method_id do |x|
          instance_variable_set(&quot;@#{attr}&quot;, x)
        end
        method_name.chop!
        define_method method_name.to_sym do
          instance_variable_get &quot;@#{attr}&quot;
        end
      end
      instance_variable_set(&quot;@#{attr}&quot;, args[0])
    end
  end

end

if __FILE__ == $0
  class ModuleTester &lt; Test::Unit::TestCase

    def test_quick_adaptor_creates_methods
      qa = QuickAdaptor.new
      qa.age = 18
      assert_equal(18, qa.age)
      qa.age = 24
      assert_equal(24, qa.age)
      assert_equal(nil, qa.name)
      qa.name = 'joe'
      assert_equal('joe', qa.name)
      assert(!qa.respond_to(:nam))
    end

    def test_quick_adaptor_creates_instance_methods
      qa1 = QuickAdaptor.new
      qa1.age = 18
      qa2 = QuickAdaptor.new
      assert(qa2.respond_to?(:age=))
      assert(qa2.respond_to?(:age))
      assert_equal(nil, qa2.age)
    end

    def test_quick_singleton_adaptor_creates_singleton_methods
      qa1 = QuickSingletonAdaptor.new
      qa1.age = 18
      qa2 = QuickSingletonAdaptor.new
      # qa2 at this point should not know anything!
      assert(!qa2.respond_to?(:age=))
      assert(!qa2.respond_to?(:age))
    end

  end
end

&lt;/pre&gt;


&lt;p&gt;As a test enthusiastic I embedded the tests in the same file which also has the advantage of giving a documentation of what the code achieves.&lt;/p&gt;

&lt;p&gt;You can see that the real difference between the QuickAdaptor and QuickSingletonAdaptor classes lies in the following lines:&lt;/p&gt;

&lt;pre lang=&quot;ruby&quot;&gt;
class QuickAdaptor
  ...
  self.class.class_eval do
    define_method method_id do |x|
      ...
    end
  end
end
&lt;/pre&gt;


&lt;pre lang=&quot;ruby&quot;&gt;
class QuickSingletonAdaptor
  ...
  singleton_class = class &lt;&lt; self ; self; end
  singleton_class.instance_eval do
    define_method method_id do |x|
      ...
    end
  end
end
&lt;/pre&gt;


&lt;p&gt;You can see from the tests that the QuickAdaptor shares the knowledge it gained with its peers (other QuickAdaptor instances), whereas QuickSingletonAdaptor is an egoist, it keeps it to itself! That's why I agree with David Black that the best way to call the class that only one instance can access is singleton class because this has more expressive power than other terms (e.g metaclass, eigenclass, etc.)&lt;/p&gt;

&lt;p&gt;My goal is to act like the QuickAdaptor, to suck in all ruby knowledge and learn as fast as QuickAdaptor does while having fun at the same time!&lt;/p&gt;

&lt;p&gt;ps. I have also taken a look at how Matz's &lt;a href=&quot;http://www.ruby-doc.org/stdlib/libdoc/ostruct/rdoc/index.html&quot;&gt;OpenStruct class&lt;/a&gt; accomplishes the same (well, much more :) ). It uses a table of fields where each new &quot;member method&quot; is defined. Nice.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>