<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:georss="http://www.georss.org/georss" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><id>tag:blogger.com,1999:blog-897393976538678091</id><updated>2009-10-13T05:08:12.539+02:00</updated><title type="text">Keep It Simple - Make It Simpler</title><subtitle type="html">&lt;small&gt;Alain Ravet&lt;/small&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.ravet.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/alainravet" type="application/atom+xml" /><feedburner:emailServiceId>alainravet</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-8105523052547248322</id><published>2007-10-05T11:29:00.000+02:00</published><updated>2007-10-05T21:51:14.019+02:00</updated><title type="text">Rails 1.2.4 changelogs</title><content type="html">&lt;div&gt;&lt;a href="http://weblog.rubyonrails.com/2007/10/5/rails-1-2-4-maintenance-release"&gt;Official announcement&lt;/a&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;The latest - and last - release in the Rails 1.2.x familly.
&lt;h1 class="writeboard"&gt;Rails 1.2.4 changelogs&lt;/h1&gt;&lt;div class="writeboardbody"&gt;  &lt;p&gt;&lt;a href="http://dev.rubyonrails.org/changeset/7741"&gt;http://dev.rubyonrails.org/changeset/7741&lt;/a&gt;&lt;/p&gt;&lt;p&gt;
Indivitual changelogs : &lt;a href="http://dev.rubyonrails.org/browser/tags/rel_1-2-4/actionpack/CHANGELOG?rev=7741"&gt;actionpack&lt;/a&gt;, &lt;a href="http://dev.rubyonrails.org/browser/tags/rel_1-2-4/activerecord/CHANGELOG?rev=7741"&gt;activerecord&lt;/a&gt;, &lt;a href="http://dev.rubyonrails.org/browser/tags/rel_1-2-4/activesupport/CHANGELOG?rev=7741"&gt;activesupport&lt;/a&gt;, &lt;a href="http://dev.rubyonrails.org/browser/tags/rel_1-2-4/railties/CHANGELOG?rev=7741"&gt;railsties&lt;/a&gt;&lt;/p&gt;&lt;p&gt;root/tags/rel_1-2-4/&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;railties&lt;/span&gt;&lt;/span&gt;/CHANGELOG
&lt;strong&gt;1.2.4&lt;/strong&gt; (October 4th, 2007)&lt;/p&gt; &lt;ul&gt;
&lt;li&gt;Add a new rake task to aid debugging of named routes.
&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;$ &lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;rake routes&lt;/span&gt;&lt;/li&gt;  &lt;li&gt;use Gem.find_name instead of search when freezing gems.  Prevent false positives for other gems with rails in the name. Closes #8729 [wselman]&lt;/li&gt;  &lt;li&gt;Fix syntax error in dispatcher than wrecked failsafe responses.  #8625 [mtitorenko]&lt;/li&gt;
&lt;li&gt;Add Active Resource to rails:freeze:edge and drop Action Web Service.  #8205 [underbluewaters, Jeremy Kemper]&lt;/li&gt;
&lt;li&gt;Give generate scaffold a more descriptive database message.  Closes #7316 [jeremymcanally]&lt;/li&gt;
&lt;li&gt;Canonicalize &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT by using File.expand_path on Windows, which doesn’t have to worry about symlinks, and Pathname#realpath elsewhere, which respects symlinks in relative paths but is incompatible with Windows.  #6755 [Jeremy Kemper, trevor]&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;root/tags/rel_1-2-4/&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;activesupport&lt;/span&gt;/CHANGELOG
&lt;strong&gt;1.4.3&lt;/strong&gt; (October 4th, 2007)&lt;/p&gt;&lt;ul&gt; &lt;li&gt;Demote Hash#to_xml to use XmlSimple#xml_in_string so it can’t read files or stdin.  #8453 [candlerb, Jeremy Kemper]&lt;/li&gt;
&lt;li&gt;Document Object#blank?.  #6491 [Chris Mear]&lt;/li&gt;
&lt;li&gt;Update Dependencies to ignore constants inherited from ancestors. Closes #6951. [Nicholas Seckar]&lt;/li&gt;
&lt;li&gt;Improved multibyte performance by relying less on exception raising #8159 [Blaine]&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;root/tags/rel_1-2-4/&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;activerecord&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;/CHANGELOG
&lt;strong&gt;1.15.4&lt;/strong&gt; (October 4th, 2007)&lt;/p&gt;&lt;ul&gt; &lt;li&gt;Fix #count on a has_many :through association so that it recognizes the :uniq option. Closes #8801 [lifofifo]&lt;/li&gt;
&lt;li&gt;Don’t clobber includes passed to has_many.count [danger]&lt;/li&gt;
&lt;li&gt;Make sure has_many uses :include when counting [danger]&lt;/li&gt;
&lt;li&gt;Save associated records only if the association is already loaded.  #8713 [blaine]&lt;/li&gt;
&lt;li&gt;Changing the :default Date format doesn’t break date quoting.  #6312 [bshand, Elias]&lt;/li&gt;
&lt;li&gt;Allow nil serialized attributes with a set class constraint. #7293 [sandofsky]&lt;/li&gt;
&lt;li&gt;belongs_to assignment creates a new proxy rather than modifying its target in-place.  #8412 [mmangino@elevatedrails.com]&lt;/li&gt;
&lt;li&gt;Fix column type detection while loading fixtures.  Closes #7987 [roderickvd]&lt;/li&gt;
&lt;li&gt;Document deep eager includes.  #6267 [Josh Susser, Dan Manges]&lt;/li&gt;
&lt;li&gt;Oracle: extract column length for &lt;span class="caps"&gt;CHAR&lt;/span&gt; also.  #7866 [ymendel]&lt;/li&gt;
&lt;li&gt;Small additions and fixes for ActiveRecord documentation.  Closes #7342 [jeremymcanally]&lt;/li&gt;
&lt;li&gt;SQLite: binary escaping works with $KCODE=’u’.  #7862 [tsuka]&lt;/li&gt;
&lt;li&gt;Improved cloning performance by relying less on exception raising #8159 [Blaine]&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;root/tags/rel_1-2-4/&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;actionpack&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;/CHANGELOG
&lt;strong&gt;1.13.4&lt;/strong&gt; (October 4th, 2007)&lt;/p&gt;&lt;ul&gt; &lt;li&gt;Only accept session ids from cookies, prevents session fixation attacks.  [bradediger]&lt;/li&gt;
&lt;li&gt;Change the resource seperator from&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt; ; &lt;/span&gt;&lt;/span&gt;to&lt;span class="Apple-style-span" style="color: rgb(255, 0, 0);"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt; /&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;    ## foos/1&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;;edit&lt;/span&gt;&lt;/span&gt; ==&gt; foos/1&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;/edit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;change the generated routes to use the new-style named routes.
            e.g.  &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;new_&lt;/span&gt;&lt;/span&gt;group_user_path(@group) instead of group&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;new&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span" style="color: rgb(51, 102, 255);"&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;user_path(@group). [pixeltrix]&lt;/li&gt;
&lt;li&gt;Integration tests: introduce methods for other &lt;span class="caps"&gt;HTTP&lt;/span&gt; methods.  #6353 [caboose]&lt;/li&gt;
&lt;li&gt;Improve performance of action caching. Closes #8231 [skaes]&lt;/li&gt;
&lt;li&gt;Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes]
After filters will &lt;strong&gt;no longer&lt;/strong&gt; be run if an around_filter fails to yield, users relying on
this behaviour are advised to put the code in question after a yield statement in an around filter.&lt;/li&gt;
&lt;li&gt;Allow you to delete cookies with options. Closes #3685 [josh, Chris Wanstrath]&lt;/li&gt;
&lt;li&gt;Deprecate pagination. Install the classic_pagination plugin (&lt;span class="Apple-style-span"  style="font-family:courier new;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;span class="Apple-style-span" style="font-style: italic;"&gt;svn://errtheblog.com/svn/plugins/classic_pagination&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;) for forward compatibility, or move to the superior &lt;a href="http://agilewebdevelopment.com/plugins/will_paginate"&gt;will_paginate&lt;/a&gt; plugin (&lt;span class="Apple-style-span" style="font-style: italic;"&gt;&lt;span class="Apple-style-span"  style="font-family:courier new;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;svn://errtheblog.com/svn/plugins/will_paginate&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;).  #8157 [Mislav Marohnic]&lt;/li&gt;
&lt;li&gt;Fix filtered parameter logging with nil parameter values.  #8422 [choonkeat]&lt;/li&gt;
&lt;li&gt;Integration tests: alias xhr to xml_http_request and add a request_method argument instead of always using &lt;span class="caps"&gt;POST&lt;/span&gt;.  #7124 [Nik Wakelin, Francois Beausoleil, Wizard]&lt;/li&gt;
&lt;li&gt;Document caches_action.  #5419 [Jarkko Laine]&lt;/li&gt;
&lt;li&gt;observe_form always sends the serialized form.  #5271 [manfred, normelton@gmail.com]&lt;/li&gt;
&lt;li&gt;Update UrlWriter to accept :anchor parameter. Closes #6771. [octopod]&lt;/li&gt;
&lt;li&gt;Replace the current block/continuation filter chain handling by an implementation based on a simple loop.  Closes #8226 [Stefan Kaes]&lt;/li&gt;
&lt;li&gt;Return the string representation from an Xml Builder when rendering a partial.  #5044 [tpope]&lt;/li&gt;
&lt;li&gt;Cleaned up, corrected, and mildly expanded ActionPack documentation.  Closes #7190 [jeremymcanally]&lt;/li&gt;
&lt;li&gt;Small collection of ActionController documentation cleanups.  Closes #7319 [jeremymcanally]&lt;/li&gt;
&lt;li&gt;Performance: patch cgi/session/pstore to require digest/md5 once rather than per #initialize.  #7583 [Stefan Kaes]&lt;/li&gt;
&lt;li&gt;Deprecation: verification with :redirect_to =&gt; :named_route shouldn’t be deprecated.  #7525 [Justin French]&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-8105523052547248322?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/8105523052547248322/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=8105523052547248322" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/8105523052547248322" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/8105523052547248322" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/10/rails-124-changelogs.html" title="Rails 1.2.4 changelogs" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-6715273245631502364</id><published>2007-07-25T10:27:00.001+02:00</published><updated>2007-07-25T10:31:59.704+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><title type="text">yield</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_UNxs-LAcbP0/RqcKeJEyUtI/AAAAAAAAAIw/i5XZBgJNt1A/s1600-h/Image+2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_UNxs-LAcbP0/RqcKeJEyUtI/AAAAAAAAAIw/i5XZBgJNt1A/s400/Image+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5091049416713982674" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-6715273245631502364?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/6715273245631502364/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=6715273245631502364" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/6715273245631502364" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/6715273245631502364" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/07/yield.html" title="yield" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_UNxs-LAcbP0/RqcKeJEyUtI/AAAAAAAAAIw/i5XZBgJNt1A/s72-c/Image+2.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-938042973644587215</id><published>2007-05-16T00:29:00.000+02:00</published><updated>2007-05-16T02:01:01.885+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="technical" /><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title type="text">2. It's best to do one thing really, really well.   (Rails refactoring with painless AOP)</title><content type="html">I like &lt;a href="http://www.google.com/corporate/today.html"&gt;Google philosophy&lt;/a&gt; a lot, especially Thing Number 9 :
&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;9. You can be serious without a suit&lt;/span&gt;.&lt;/li&gt;&lt;/ul&gt;, but that's not the subject of this sermon; today I'd like to tell you about Thing Number Two (TNT) :
&lt;ul style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;li&gt;2. It's best to do one thing really, really well.&lt;/li&gt;&lt;/ul&gt;- Amen -, and its IT translation  : the "&lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;Separation Of Concerns&lt;/a&gt;".

At the humble coder's level, separated concerns make for a more readable code.

Counter example:&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Benchmark&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;measure&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;{&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;Stuff.fetch_all&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;}&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;puts&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;span title="String" class="k"&gt;time spent: &lt;/span&gt;&lt;span title="String" class="il"&gt;&lt;span title="String" class="idl"&gt;#{&lt;/span&gt;&lt;span title="String" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="String" class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span title="String" class="k"&gt; &lt;/span&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;a href="http://www.xprogramming.com/Practices/PracSimplest.html"&gt;It's ugly, but it works&lt;/a&gt;.
It works, but it's ugly: this code does TWO completely unrelated things:
&lt;ol&gt;&lt;li&gt;fetch some stuff, and &lt;/li&gt;&lt;li&gt;benchmark  an action, any action&lt;/li&gt;&lt;/ol&gt;We MUST find a way to separate those 2 concerns:

The first and main concern is obvious :&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Stuff&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;fetch_all&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Comment" class="c"&gt;# &amp;lt;&amp;lt;--- CONCERN 1 &lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
The second concern is easy to code&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu"&gt;generic_benchmarking_method&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Benchmark&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;measure&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;action_to_measure&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;   &lt;/span&gt;&lt;span title="Comment" class="c"&gt;# &amp;lt;&amp;lt;--- (concern 1)       &lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;}&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;puts&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;span title="String" class="k"&gt;time spent : &lt;/span&gt;&lt;span title="String" class="il"&gt;&lt;span title="String" class="idl"&gt;#{&lt;/span&gt;&lt;span title="String" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="String" class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span title="String" class="k"&gt;}&lt;/span&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Comment" class="c"&gt;# &amp;lt;&amp;lt;--- CONCERN 2&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;   &lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
but it's difficult to connect to the first method, because :
&lt;ul&gt;&lt;li&gt;users of concern 1 should not have to know about concern 2 =&gt; they will just call the first method&lt;/li&gt;&lt;li&gt;as the benchmarking action is completely independent from the action it measures, this action should be passed as a parameter in some way&lt;/li&gt;&lt;/ul&gt;The solution: &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;piggy-back&lt;/span&gt; the benchmarking method on the fetching method, transparently.

Q: how do you piggy back ?
A: with Rails' &lt;a href="http://caboo.se/doc/classes/Module.html#M003437"&gt;alias_method_chain&lt;/a&gt;  , and some "convention over configuration magic"**
(** hint: it's all in the &lt;i&gt;methods naming&lt;/i&gt;)

Take a deep breath and watch the mystery unveil :
&lt;h4&gt;Before&lt;/h4&gt;&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Benchmark&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;measure&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;{&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;Stuff.fetch_all&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;}&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;puts&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;span title="String" class="k"&gt;time spent: &lt;/span&gt;&lt;span title="String" class="il"&gt;&lt;span title="String" class="idl"&gt;#{&lt;/span&gt;&lt;span title="String" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="String" class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span title="String" class="k"&gt; &lt;/span&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h4&gt;After&lt;/h4&gt;&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Comment" class="c"&gt;# concern 1: just do it.&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Stuff&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;fetch_all&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Comment" class="c"&gt;# concern 2: just benchmark it.&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Method" class="fu hiline"&gt;_with_benchmarking&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Constant" class="co"&gt;Benchmark&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;measure&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;{&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT hiline"&gt;_without_benchmarking&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;}&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;puts&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;span title="String" class="k"&gt;time spent: &lt;/span&gt;&lt;span title="String" class="il"&gt;&lt;span title="String" class="idl"&gt;#{&lt;/span&gt;&lt;span title="String" class="NO_HIGHLIGHT"&gt;benchmark&lt;/span&gt;&lt;span title="String" class="idl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span title="String" class="k"&gt; &lt;/span&gt;&lt;span title="String" class="dl"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;alias_method_chain&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:&lt;/span&gt;&lt;span title="Symbol" class="sy hiline2"&gt;fetch_stuff&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:&lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;benchmarking&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
That's it : &lt;code&gt;alias_method_chain&lt;/code&gt; wrapped &lt;span class="hiline"&gt;benchmarking&lt;/span&gt; around &lt;span class="hiline2"&gt;fetch_stuff&lt;/span&gt;. After line 14 has been parsed, calls to the original &lt;code&gt;fetch_stuff&lt;/code&gt; are redirected to &lt;code&gt;fetch_stuff_with_benchmarking&lt;/code&gt;, and &lt;code&gt;fetch_stuff_without_benchmarking&lt;/code&gt; points to the original &lt;code&gt;fetch_stuff&lt;/code&gt;. It's transparent and automatic. All you have to do is respect the naming convention : &lt;code&gt;&lt;span style="color: rgb(255, 0, 0); font-weight: bold; font-style: italic;"&gt;with&lt;/span&gt;&lt;/code&gt;  and &lt;code&gt;&lt;span style="font-style: italic; color: rgb(255, 0, 0); font-weight: bold;"&gt;without&lt;/span&gt;&lt;/code&gt;.

That's it.

This &lt;a href="http://dev.rubyonrails.org/browser/trunk/activesupport/lib/active_support/core_ext/module/aliasing.rb?rev=4276"&gt;method&lt;/a&gt; was introduced in Rails a year ago to DRY up the internals. There is no reason your code should not benefit shamelessly from it too. Strive for it. You'll thank me later.

&lt;img src="http://3.bp.blogspot.com/_UNxs-LAcbP0/RjTpErRKEII/AAAAAAAAACY/HrrVTr_nDlI/s200/Photo_11-square.jpg" style="" border="0" /&gt;
API :
&lt;ul&gt;&lt;li&gt;&lt;a href="http://caboo.se/doc/classes/Module.html#M003437"&gt;http://caboo.se/doc/classes/Module.html#M003437&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Articles :
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/*%20http://weblog.rubyonrails.org/2006/4/26/new-in-rails-module-alias_method_chain"&gt;http://weblog.rubyonrails.org/2006/4/26/new-in-rails-module-alias_method_chain&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://errtheblog.com/post/1109"&gt;http://errtheblog.com/post/1109&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-938042973644587215?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/938042973644587215/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=938042973644587215" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/938042973644587215" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/938042973644587215" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/05/2-its-best-to-do-one-thing-really.html" title="2. It's best to do one thing really, really well.   (Rails refactoring with painless AOP)" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_UNxs-LAcbP0/RjTpErRKEII/AAAAAAAAACY/HrrVTr_nDlI/s72-c/Photo_11-square.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-5680095751910545285</id><published>2007-05-13T00:17:00.000+02:00</published><updated>2007-05-13T11:20:24.606+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="technical" /><title type="text">Rails plugins : group_by(environment)</title><content type="html">If your &lt;code&gt;vendor/plugins&lt;/code&gt; directory gets overcrowded and you use some test/development-specific plugins, here is a quick way to clean up your source tree :

&lt;h4&gt;Step 1: split the &lt;code&gt;vendor/plugins&lt;/code&gt; directory&lt;/h4&gt; Create two directories : &lt;span style="font-family: monospace;"&gt;vendor&lt;/span&gt;&lt;code&gt;/plugins-development&lt;/code&gt; and &lt;span style="font-family: monospace;"&gt;vendor/plugins-&lt;/span&gt;&lt;code&gt;test&lt;/code&gt;, and move your plugins accordingly :

&lt;img class="illu" src="http://3.bp.blogspot.com/_UNxs-LAcbP0/RkY90LRKEJI/AAAAAAAAACg/uTJmKg7wRvk/s200/plugins_dirs.png" border="0" /&gt;

&lt;h4&gt;Step 2: tell Rails where to find the moved plugins&lt;/h4&gt;
In &lt;code&gt;config/environment/development.rb&lt;/code&gt; add this line:

&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;config&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;plugin_paths&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;push&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;'&lt;/span&gt;&lt;span title="String" class="k"&gt;vendor/plugins-development&lt;/span&gt;&lt;span title="String" class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;uniq!&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

, and in &lt;code&gt;config/environment/test.rb&lt;/code&gt; add:

&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;config&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;plugin_paths&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;push&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;'&lt;/span&gt;&lt;span title="String" class="k"&gt;vendor/plugins-test&lt;/span&gt;&lt;span title="String" class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;uniq!&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

And that's it.

&lt;img src="http://3.bp.blogspot.com/_UNxs-LAcbP0/RjTpErRKEII/AAAAAAAAACY/HrrVTr_nDlI/s200/Photo_11-square.jpg" style="" border="0" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-5680095751910545285?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/5680095751910545285/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=5680095751910545285" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/5680095751910545285" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/5680095751910545285" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/05/rails-plugins-sortbyenvironment.html" title="Rails plugins : group_by(environment)" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_UNxs-LAcbP0/RkY90LRKEJI/AAAAAAAAACg/uTJmKg7wRvk/s72-c/plugins_dirs.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-7500791533384361913</id><published>2007-05-10T01:59:00.000+02:00</published><updated>2007-05-10T16:08:43.786+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="technical" /><category scheme="http://www.blogger.com/atom/ns#" term="refactoring" /><title type="text">Rails refactoring with delegate(..)</title><content type="html">&lt;div style="text-align: center;"&gt;“When something is too hard it means that you’re not cheating enough.”
&lt;/div&gt;
&lt;a href="http://project.ioni.st/post/579#quote_579"&gt;DHH&lt;/a&gt;


&lt;strong&gt;Before:&lt;/strong&gt;&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span title="Reserved" class="r"&gt;class&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Class" class="cl"&gt;Cart&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu"&gt;initialize&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Instance Variable" class="iv"&gt;@items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;    &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;[&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;]&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt; &lt;/span&gt;&lt;span title="Method" class="fu loline"&gt;size&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;   &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;    &lt;/span&gt;&lt;span title="Instance Variable" class="iv loline"&gt;@items&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT loline"&gt;size&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;    &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt; &lt;/span&gt;&lt;span title="Method" class="fu loline"&gt;clear&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;  &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;    &lt;/span&gt;&lt;span title="Instance Variable" class="iv loline"&gt;@items&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT loline"&gt;clear&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;   &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt; &lt;/span&gt;&lt;span title="Method" class="fu loline"&gt;empty?&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;    &lt;/span&gt;&lt;span title="Instance Variable" class="iv loline"&gt;@items&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT loline"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT loline"&gt;empty?&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT loline"&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r loline"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;attr_reader&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;After&lt;/h4&gt;&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span title="Reserved" class="r"&gt;class&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Class" class="cl"&gt;Cart&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu"&gt;initialize&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Instance Variable" class="iv"&gt;@items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;    &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;[&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;]&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT hiline"&gt;delegate&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;:clear&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT hiline"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;:empty?&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT hiline"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;:size&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT hiline"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;:to&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT hiline"&gt;=&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT hiline"&gt;&amp;gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT hiline"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy hiline"&gt;:items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;attr_reader&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;strong&gt;What it does:&lt;/strong&gt;

When you call
&lt;code&gt;
  cart.size
&lt;/code&gt;
, Rails &lt;em&gt;delegates&lt;/em&gt; the &lt;i&gt;size()&lt;/i&gt; method call to the &lt;i&gt;items&lt;/i&gt; object and executes:
&lt;code&gt;
  cart.items.size
&lt;/code&gt;

&lt;strong&gt;How it works:&lt;/strong&gt;
If you look at the &lt;a href="http://caboo.se/doc/classes/Module.html#M003442"&gt;source&lt;/a&gt;, you'll notice that Rails actually generates 3 methods equivalent to the code we have just removed (see 'Before'), and injects them in the class code. The behaviour does not change; it's just a shorter way to write this code.


Should you want (be careful) to delegate ALL the unknown methods calls, you could write :&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;span title="Comment" class="c"&gt;# delegate unknown methods calls to @items&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu"&gt;method_missing&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;method&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;block&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;/span&gt;&lt;span title="Instance Variable" class="iv"&gt;@items&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;send&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;method&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;*&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;args&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;amp;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;block&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;strong&gt;

API doc :&lt;/strong&gt;
   &lt;a href="http://caboo.se/doc/classes/Module.html#M003442"&gt;http://caboo.se/doc/classes/Module.html#M003442&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-7500791533384361913?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/7500791533384361913/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=7500791533384361913" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/7500791533384361913" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/7500791533384361913" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/05/rails-refactoring-with-delegate.html" title="Rails refactoring with &lt;em&gt;delegate(..)&lt;/em&gt;" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-8736810964567268625</id><published>2007-05-03T23:36:00.000+02:00</published><updated>2007-08-02T20:27:56.701+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tip" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><category scheme="http://www.blogger.com/atom/ns#" term="technical" /><title type="text">&lt;% cache_unless(params.include?('no_cache_please') , ... do %&gt;</title><content type="html">Is adding fragments/actions caching worth it for &lt;b&gt;&lt;i&gt;your&lt;/i&gt;&lt;/b&gt; Rails application, on &lt;b&gt;&lt;i&gt;your&lt;/i&gt;&lt;/b&gt; server?
&lt;ol&gt;&lt;li&gt;Adding caching to an application complexifies the code (and can be hard to test).
&lt;/li&gt;&lt;li&gt;The caching efficiency (in req/sec) depends on many factors : RAM size, CPU power, HD speed, DB caches size, ... A spectacular improvement measured on an old sluggish staging server could be barely noticeable on a modern 4-core machine with 8GB of RAM and the fastest disk money can buy.
&lt;/li&gt;&lt;/ol&gt;Is caching worth it for your application, on your server? It depends.

For example, in &lt;a href="http://blog.ravet.com/2007/04/vooruit-on-rails.html"&gt;the Vooruit project&lt;/a&gt; the staging server is an old fart with a slow HD and barely enough memory to run 1 Mongrel instance. This is the machine I used to hand-tune the fragment-caching code. &lt;b&gt;I needed to confirm&lt;/b&gt; that caching was also improving significantly the performance on the production server.

Tip: &lt;ul&gt;&lt;li&gt;disable remotely some/all caching on the production server through a parameter in the url:&lt;/li&gt;&lt;/ul&gt;
&lt;code style="padding-left: 150px;"&gt;http://example.com/foobar?&lt;span style="color:red;"&gt;no_cache_please&lt;/span&gt;&lt;/code&gt;
&lt;table class="CodeRay"&gt;&lt;tbody&gt;&lt;tr&gt;
&lt;td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;

&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;/pre&gt;&lt;/td&gt;
&lt;td class="code"&gt;&lt;pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"&gt;&lt;tt&gt;&lt;/tt&gt;&lt;tt&gt;&lt;/tt&gt;&lt;span title="Constant" class="co"&gt;In the views you want to test&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;:&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;&lt;/tt&gt;&lt;/span&gt;
&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;---------------------------------&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;lt;&lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;% &lt;/span&gt;&lt;span title="String" class="k"&gt;cache_unless(params.include?('no_cache_please')&lt;/span&gt;&lt;span title="String" class="dl"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:genre&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;params&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;[&lt;/span&gt;&lt;span title="Symbol" class="sy"&gt;:genre&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;]&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;do&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;%&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;...&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;the&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;cached&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;code&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;html&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;and&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;erb&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;lt;&lt;/span&gt;&lt;span title="String" class="s"&gt;&lt;span title="String" class="dl"&gt;% &lt;/span&gt;&lt;span title="String" class="k"&gt;end&lt;/span&gt;&lt;span title="String" class="dl"&gt; &lt;/span&gt;&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;%&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;gt;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;      &lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Constant" class="co"&gt;In&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;application_helper&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;rb&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;:&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;--------------------------&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;def&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Method" class="fu"&gt;cache_unless&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;condition&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;name&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;=&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;{&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;}&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;block&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;if&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;condition&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;then&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;block&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;.&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;call&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;;&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;return&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;cache&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;(&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;name&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;,&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt; &lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;&amp;amp;&lt;/span&gt;&lt;span title="Ident" class="NO_HIGHLIGHT"&gt;block&lt;/span&gt;&lt;span title="Operator" class="NO_HIGHLIGHT"&gt;)&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;/span&gt;&lt;span title="Reserved" class="r"&gt;end&lt;/span&gt;&lt;span title="Space" class="NO_HIGHLIGHT"&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
Now you can turn the caching on and off to &lt;a href="http://peepcode.com/products/benchmarking-with-httperf"&gt;measure&lt;/a&gt; the speed increase on any remote machine:
&lt;code&gt;&lt;pre&gt;
httperf --server production.example.com --uri /nl --num-conns 100
Reply rate [replies/s]: min 6.6 avg 6.8 max 7.0 stddev 0.3 (2 samples)
Reply rate [replies/s]: min 5.6 avg 6.6 max 7.2 stddev 0.9 (3 samples)


httperf --server production.example.com --uri /nl&lt;span style=""&gt;?no_cache&lt;/span&gt; --num-conns 100
Reply rate [replies/s]: min 7.0 avg 7.1 max 7.2 stddev 0.1 (2 samples)
Reply rate [replies/s]: min 3.2 avg 5.0 max 7.2 stddev 1.7 (4 samples)
&lt;/pre&gt;&lt;/code&gt;

Was caching worth it? In this case, barely.


&lt;strong&gt;Updated:&lt;/strong&gt;&lt;br /&gt;
Clarified that this article is mostly about fragments and actions caching.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-8736810964567268625?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/8736810964567268625/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=8736810964567268625" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/8736810964567268625" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/8736810964567268625" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/05/is-caching-worth-it-adding-caching-to.html" title="&lt;% cache_unless(params.include?('no_cache_please') , ... do %&gt;" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-4713741342252577788</id><published>2007-05-01T18:24:00.000+02:00</published><updated>2007-05-01T20:30:45.701+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="text" /><title type="text">Bugs have a life of their own</title><content type="html">I've never put any bug in my code. They all sneeked in, on their own, without my consent.

Bugs have a life of their own. Bugs were born and normally live in Bugland. When they want to take some vacation, they visit their family that happens to live in your code base. Some like it so much abroad that they decide stay longer, or even become permanent resident (MS products).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-4713741342252577788?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/4713741342252577788/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=4713741342252577788" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/4713741342252577788" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/4713741342252577788" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/05/bugs-have-life-of-their-own.html" title="Bugs have a life of their own" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-897393976538678091.post-5851325119699423033</id><published>2007-04-30T21:23:00.001+02:00</published><updated>2007-05-03T09:51:06.637+02:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="launch" /><category scheme="http://www.blogger.com/atom/ns#" term="vooruit" /><category scheme="http://www.blogger.com/atom/ns#" term="belgium" /><title type="text">The Vooruit Kunstcentrum : on Rails</title><content type="html">&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_80dfw5qzq6" style="height: 121px; width: 392px;" /&gt;

The &lt;a href="http://www.vooruit.be/"&gt;Vooruit Kunstcentrum&lt;/a&gt; in Ghent (Belgium), Flanders' biggest art center, has got a brand new web site. And it's Web2.0-ish. A lot. It's only in Dutch at this moment, but the English version is on the conveyor belt.

We launched on April 20Th 2007, after 3 months of intense development - 100% in &lt;a href="http://rubyonrails.org/"&gt;Ruby On Rails&lt;/a&gt; - and too many sleepless nights. (Yes, I do sleep better now, thank you for asking).

&lt;ul&gt;
&lt;li value="2"&gt;&lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;postID=5851325119699423033#in_the_box"&gt;What's     in the box?&lt;/a&gt;   &lt;/li&gt; &lt;li value="2"&gt;&lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;amp;postID=5851325119699423033#you_can"&gt;You can...&lt;/a&gt; &lt;/li&gt; &lt;li value="2"&gt; &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;postID=5851325119699423033#each_production"&gt;Each production...&lt;/a&gt; &lt;/li&gt; &lt;li value="2"&gt; &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;amp;postID=5851325119699423033#the_community"&gt;The community&lt;/a&gt; &lt;/li&gt; &lt;li value="2"&gt;  &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;postID=5851325119699423033#the_future"&gt;The future&lt;/a&gt;   &lt;/li&gt; &lt;li&gt;  &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;amp;postID=5851325119699423033#the_team"&gt;The team.&lt;/a&gt;   &lt;/li&gt; &lt;li&gt;  &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;postID=5851325119699423033#kismis"&gt;"Keep     It Simple - Make It Simpler"&lt;/a&gt;   &lt;/li&gt;  &lt;li&gt;     &lt;a href="http://www2.blogger.com/post-edit.g?blogID=897393976538678091&amp;amp;postID=5851325119699423033#bye"&gt;I'll be back&lt;/a&gt;   &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;   &lt;a id="in_the_box"&gt;&lt;/a&gt; What's in the box? &lt;/h3&gt; A art-program browser on steroids (&lt;a href="http://www.vooruit.be/nl/productions" title="/productions"&gt;/productions&lt;/a&gt; ) + an art-lovers community cocoon (&lt;a href="http://www.vooruit.be/nl/community" title="/community"&gt;/community&lt;/a&gt; ).

OK. Let's have a look at the features.
&lt;h3&gt;   &lt;a id="you_can"&gt;&lt;/a&gt; You can : &lt;/h3&gt; &lt;ul&gt;   &lt;li&gt;     just &lt;a href="http://vooruit.be/"&gt;have a peek&lt;/a&gt; :   &lt;/li&gt; &lt;/ul&gt;&lt;a href="http://www.vooruit.be/nl"&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_83dqhdq2g3" style="height: 220px; width: 400px;" align="top" border="1" hspace="5" vspace="5" /&gt;&lt;/a&gt;

&lt;ul&gt;   &lt;li&gt;     , &lt;a href="http://vooruit.be/"&gt;read the headlines&lt;/a&gt;,
&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_858m2nfgcc" style="height: 189px; width: 268px;" align="top" /&gt;

&lt;ul&gt;   &lt;li&gt;     , find a &lt;a href="http://vooruit.be/nl/concerts/2007/5"&gt;concert in     April&lt;/a&gt;, a &lt;a href="http://www2.blogger.com/want"&gt;podium event next     week&lt;/a&gt; or a &lt;a href="http://vooruit.be/nl/parties/2007/5/26"&gt;party on May     26Th&lt;/a&gt;   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_86hj4t6m4r" style="height: 305px; width: 264px;" /&gt;

&lt;ul&gt;   &lt;li&gt;     , &lt;a href="http://vooruit.be/nl/productions/1028#speellijst"&gt;buy     tickets&lt;/a&gt;,   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_87g9bpwpcc" style="height: 173px; width: 270px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     , follow the suggestions
&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_88cp3chshb" style="height: 176px; width: 264px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     subscribe to the "&lt;a href="http://vooruit.be/nl/feeds/concerts"&gt;new     concerts" feed&lt;/a&gt;,   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_89c4tjhzgj" style="height: 220px; width: 204px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     see what's on the menu in series like &lt;a href="http://vooruit.be/nl/series/28"&gt;the     Courtisane Festival 2007 voor kortfilm, video en nieuwe media :&lt;/a&gt;    &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_90fhg3b9fx" style="height: 269px; width: 269px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     or just be lazy and follow     &lt;a href="http://www.vooruit.be/nl/tags/218" title="tag: kortfilm"&gt;tags:&lt;/a&gt;   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_91c7p5wxhq" style="height: 131px; width: 259px;" /&gt;



&lt;h3&gt;   &lt;a id="each_production"&gt;&lt;/a&gt; Each production (concert, theater, ..) &lt;/h3&gt; &lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_92cd69mdht" style="height: 92px; width: 400px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     gets its own     &lt;a href="http://www.vooruit.be/nl/productions/1010" title="mini-site"&gt;mini-site&lt;/a&gt;     with a presentation of the event, articles by the Vooruit editors or     external writers,     ...&lt;a href="http://www.vooruit.be/nl/productions/1010/media"&gt;&lt;/a&gt;   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_93gp5q45gj" style="height: 390px; width: 397px;" /&gt;

&lt;ul&gt;   &lt;li&gt;     ..,and &lt;a href="http://www.vooruit.be/nl/productions/1010/media"&gt; photos,     audios and videos&lt;/a&gt;   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_97hf56n6ft" style="height: 395px; width: 491px;" /&gt;

plus:
&lt;ul&gt;   &lt;li&gt;     gets its own community area where registered members (it could be     &lt;a href="http://www.vooruit.be/nl/signup"&gt;you)&lt;/a&gt; can recommend, vote, post     short comments, tips, reviews, send pictures,
&lt;/li&gt; &lt;/ul&gt;
&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_79pzv66hxj" style="height: 152px; width: 284px;" align="top" border="1" hspace="5" /&gt;


For popular events, you can see &lt;a href="http://www.vooruit.be/nl/productions/989/want_to_see" title="who plans to attend"&gt;who plans to attend&lt;/a&gt;, or attended:
&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_98d3wqxsgz" style="height: 324px; width: 400px;" /&gt;



&lt;h3&gt;   &lt;a id="the_community"&gt;&lt;/a&gt; The Community : &lt;/h3&gt;
If you want to check the community pulse, go no further than the &lt;a href="http://www.vooruit.be/nl/community"&gt;Community&lt;/a&gt; area :

&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_99hqkn52gz" style="height: 106px; width: 369px;" /&gt;

and
&lt;ul&gt;   &lt;li&gt;     see who's the member of the week :
&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_108ddzwnjd7" style="height: 150px; width: 273px;" /&gt;

&lt;ul&gt;   &lt;li&gt;     ..or the latest 9 members   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_101cj5bm3gh" style="height: 374px; width: 263px;" /&gt;

&lt;ul&gt;   &lt;li&gt;     find out what members are talking about :   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_102drk38vgj" style="height: 160px; width: 415px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     or the latest photos they posted :   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_103cbwf5wf6" style="height: 230px; width: 264px;" /&gt;


That's all folks. We did our bit. Now it's your turn : create an account.

&lt;a href="http://www.vooruit.be/nl/signup"&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_10576n7shck" style="height: 71px; width: 72px;" /&gt;&lt;/a&gt;
, and we'll create a place just for you,
&lt;ul&gt;   &lt;li&gt;where you can tell us who you are, what you like:   &lt;/li&gt; &lt;/ul&gt;&lt;ul&gt; &lt;/ul&gt;
&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_111vjchcjff" style="height: 290px; width: 400px;" /&gt;

&lt;ul&gt;   &lt;li&gt;, and upload your pictures :
&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_113gc9zppdb" style="height: 369px; width: 400px;" /&gt;
&lt;ul&gt;   &lt;li&gt;     , and publish your texts (Yes, you are an author)   &lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_114dcc3vns5" style="height: 284px; width: 400px;" /&gt;

&lt;ul&gt;   &lt;li&gt;     A useful feature: all the events you ever tagged, rated, reviewed, or tipped
&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_1164w76ghgd" style="height: 76px; width: 400px;" /&gt;

.. will show up in you 'Kalender' tab :

&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_118f58rp6ds" style="height: 234px; width: 400px;" /&gt;



&lt;ul&gt;&lt;li&gt;All the people you ever tagged as friends&lt;/li&gt;&lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_121hd9nqvcb" style="height: 45px; width: 196px;" /&gt;

.. will show up in your 'Friends' tab :
&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_123cgpbfkhd" style="height: 267px; width: 400px;" /&gt;

And finally,

&lt;ul&gt;   &lt;li&gt;whenever you see an article, a text, an image, a video, an audio you     like, just mark it :&lt;/li&gt; &lt;/ul&gt;&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_124fz49xz4j" style="height: 41px; width: 191px;" /&gt;

and it will show up in you 'Favourites' tab :

&lt;img class="illu" src="http://docs.google.com/File?id=ddmqwkxs_125f83spqfv" style="height: 332px; width: 400px;" /&gt;

&lt;h3&gt;   &lt;a id="the_future"&gt;&lt;/a&gt; The future of vooruit.be : &lt;/h3&gt; Following the great Google tradition, we launched in beta mode. Over the coming months, you can expect many more great features: an English version, groups, screencasts, individual users auto-blogs, and super-secret stuff I can't tell you about, (otherwise I'd have to kill you, and I don't want to do that anymore; who knows, you could become a client one day).


&lt;h3&gt;   &lt;a id="the_team"&gt;&lt;/a&gt; The Team : &lt;/h3&gt; As with most success stories, this project was a team effort.
On the client side there was :
* &lt;a href="http://vooruit.be/nl/users/3-eddy"&gt;Eddy Naert&lt;/a&gt; the client voice, the graphist, the project manager and much more : if it looks good and it's useful, it's thanks to him.
* A super great team of dedicated editors, who worked long hours, even on Sundays, to create the rich contents for you. If it's interesting, it's thanks to them.

On the developer side, there was :
* &lt;a href="http://www.workingwithrails.com/person/4679-alain-ravet"&gt;me&lt;/a&gt; (Alain Ravet), and Ruby on Rails: if it doesn't work, you know who to blame (hint: &lt;a href="http://en.wikipedia.org/wiki/Papal_infallibility"&gt;it's not 'Rails'&lt;/a&gt;)

&lt;hr /&gt;


&lt;h3&gt;   &lt;a id="kismis"&gt;&lt;/a&gt; "Keep It Simple - Make It Simpler" &lt;/h3&gt;If you came here for Ruby On Rails material, hold you breath &lt;a href="http://www.wikihow.com/Hold-Your-Breath-for-Long-Periods-of-Time"&gt;a little longer&lt;/a&gt;: starting next week, I'll post Ruby On Rails tips-and-tricks extracted from my projects in a category I call:
&lt;blockquote&gt;Keep It Simple - Make It Simpler&lt;/blockquote&gt;

Be seing you.


&lt;p class="flat"&gt;   &lt;a id="bye"&gt;&lt;/a&gt;Alain Ravet (that's me there →)    &lt;img src="http://3.bp.blogspot.com/_UNxs-LAcbP0/RjTpErRKEII/AAAAAAAAACY/HrrVTr_nDlI/s200/Photo_11-square.jpg" style="" border="0" /&gt;
&lt;/p&gt; &lt;a href="http://1.bp.blogspot.com/_UNxs-LAcbP0/RjS0kLRKEGI/AAAAAAAAACI/bAdNtZ9c0-I/s1600-h/vooruit_launch.png"&gt;
&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/897393976538678091-5851325119699423033?l=blog.ravet.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.ravet.com/feeds/5851325119699423033/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=897393976538678091&amp;postID=5851325119699423033" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/5851325119699423033" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/897393976538678091/posts/default/5851325119699423033" /><link rel="alternate" type="text/html" href="http://blog.ravet.com/2007/04/vooruit-on-rails.html" title="The Vooruit Kunstcentrum : on Rails" /><author><name>Alain Ravet</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd="http://schemas.google.com/g/2005" name="OpenSocialUserId" value="10464700513164443026" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_UNxs-LAcbP0/RjTpErRKEII/AAAAAAAAACY/HrrVTr_nDlI/s72-c/Photo_11-square.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry></feed>
