<?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/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ck4GSH8yeyp7ImA9WxNQF0U.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050</id><updated>2009-09-24T16:28:49.193+08:00</updated><title>Polymorphic Associations</title><subtitle type="html">Erol writes about Ruby on Rails, software, technology, and getting things done in the information age.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://erolfornoles.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/polymorphic_associations" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;DkUNSXY5eyp7ImA9WxdbGUk.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050.post-6306835125968166119</id><published>2008-08-17T10:23:00.006+08:00</published><updated>2008-08-17T11:38:18.823+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-17T11:38:18.823+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jRails" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby on Rails" /><category scheme="http://www.blogger.com/atom/ns#" term="jQuery" /><title>Using jQuery on Rails in 3 easy steps</title><content type="html">There are a couple of reasons why you may want to use &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; in your &lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt;' projects. It could be the shorter code. Or you may find it a little bit more unobstrusive than &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt;. Or, if you're like me, you may have been enticed by the number of &lt;a href="http://jquery.com/plugins/"&gt;plugins&lt;/a&gt; available for it.&lt;br /&gt;
&lt;br /&gt;
So how do we use it then?&lt;br /&gt;
&lt;br /&gt;
You can choose to make Prototype and jQuery work with each other, and effectively double the amount of javascript that your user downloads everytime he or she visits your site.&lt;br /&gt;
&lt;br /&gt;
Or you can switch to jQuery altogether, which is what I'll be discussing next.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Download and install jQuery&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
This should be a no-brainer. Before we can use the darned thing, we have to download and install it first.&lt;br /&gt;
&lt;br /&gt;
Download the latest version of jQuery from &lt;a href="http://docs.jquery.com/Downloading_jQuery"&gt;here&lt;/a&gt; and copy it to your public/javascripts directory. We won't be needing the Prototype/Script.aculo.us files anymore so you can delete them while you're at it.&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-size: large;"&gt;Download and install jRails&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Prototype and Script.aculo.us comes with their very own little Ruby helpers which makes life a little bit easier for us. Instead of writing:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;a href="#" onclick="new Ajax.Request('/person/4', {asynchronous:true, evalScripts:true, method:'delete'}); return false;"&amp;gt;Destroy&amp;lt;/a&amp;gt;
&lt;/pre&gt;We simply write this instead:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= link_to_remote "Destroy", :url =&amp;gt; person_url(:id =&amp;gt; @person), :method =&amp;gt; :delete %&amp;gt;
&lt;/pre&gt;Here's another example:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest', '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})&amp;nbsp;
&lt;/pre&gt;To this:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= observe_field :suggest, :url =&amp;gt; { :action =&amp;gt; :find_suggestion },
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :frequency =&amp;gt; 0.25,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :update =&amp;gt; :suggest,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :with =&amp;gt; 'q'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt;
&lt;/pre&gt;Now that we're moving to jQuery, guess what? All those nice little helpers are now broken. But not for long though.&lt;br /&gt;
&lt;br /&gt;
Introducing jRails: &lt;br /&gt;
&lt;blockquote&gt;&lt;a href="http://ennerchi.com/projects/jrails"&gt;jRails&lt;/a&gt; is a drop-in jQuery replacement for Prototype/Script.aculo.us on Rails. Using jRails, you can get all of the same default Rails helpers for javascript functionality using the lighter jQuery library.&lt;/blockquote&gt;Let's install it by running: &lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;./script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails
&lt;/pre&gt;Then include it in your layouts:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= javascript_include_tag "jquery", "jquery-ui", "jrails" %&amp;gt;
&lt;/pre&gt;Or if you weren't lazy before and deleted your Prototype/Script.aculo.us files, and you're feeling a little lazy now:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= javascript_include_tag :all %&amp;gt;
&lt;/pre&gt;&lt;span style="font-size: large;"&gt;Make a little modification on your previous Prototype/Script.aculo.us helper calls&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to change all id paramaters in your helper calls from :id or 'id' to '#id'. For example, something like this:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= observe_field :suggest, :url =&amp;gt; { :action =&amp;gt; :find_suggestion },
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :frequency =&amp;gt; 0.25,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :update =&amp;gt; :suggest,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :with =&amp;gt; 'q'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt;
&lt;/pre&gt;Needs to be changed to: &lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;%= observe_field '#suggest', :url =&amp;gt; { :action =&amp;gt; :find_suggestion },
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :frequency =&amp;gt; 0.25,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :update =&amp;gt; '#suggest',
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; :with =&amp;gt; 'q'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %&amp;gt; 
&lt;/pre&gt;Or something like this:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;render :update do |page|
&amp;nbsp; page.replace 'article', :partial =&amp;gt; 'item'
end
&lt;/pre&gt;To this:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;render :update do |page|
&amp;nbsp; page.replace '#article', :partial =&amp;gt; 'item'
end
&lt;/pre&gt;Once you've made all the necessary changes in your code, that's it. You're done. Now fire up your web server and browser and see how it works.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1878052100340831050-6306835125968166119?l=erolfornoles.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/polymorphic_associations/~4/oZTtMihNRus" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/6306835125968166119/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://erolfornoles.blogspot.com/2008/08/using-jquery-on-rails-in-3-easy-steps.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/6306835125968166119?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/6306835125968166119?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/polymorphic_associations/~3/oZTtMihNRus/using-jquery-on-rails-in-3-easy-steps.html" title="Using jQuery on Rails in 3 easy steps" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14566455241213375471" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://erolfornoles.blogspot.com/2008/08/using-jquery-on-rails-in-3-easy-steps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYFRnc6cCp7ImA9WxdbGEQ.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050.post-686700384909069254</id><published>2008-08-15T19:31:00.003+08:00</published><updated>2008-08-16T22:48:37.918+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-16T22:48:37.918+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="belongs_to" /><category scheme="http://www.blogger.com/atom/ns#" term="ActiveRecord" /><category scheme="http://www.blogger.com/atom/ns#" term="associations" /><category scheme="http://www.blogger.com/atom/ns#" term="plugin" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby on Rails" /><title>ActsAsReference: A convenient method of handling belongs_to associations in Rails</title><content type="html">In one of the projects I'm working on, I had a variety of models which needed a 'Company' field. Being the &lt;a href="http://en.wikipedia.org/wiki/Database_normalization"&gt;normalization&lt;/a&gt; and &lt;a href="http://wiki.rubyonrails.org/rails/pages/Associations"&gt;associations&lt;/a&gt; junkie that I am, I had them setup this way:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;class Company &amp;lt; ActiveRecord::Base
end

class Truck &amp;lt; ActiveRecord::Base
&amp;nbsp; belongs_to :company 
end

class Vessel &amp;lt; ActiveRecord::Base
&amp;nbsp; belongs_to :company 
end

class Container &amp;lt; ActiveRecord::Base
&amp;nbsp; belongs_to :company
end

class Depot &amp;lt; ActiveRecord::Base
&amp;nbsp; belongs_to :company
end
&lt;/pre&gt;Which is all good and well until I came to one of my form views:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;% form_for :truck, @truck, :url =&amp;gt; { :action =&amp;gt; "create" } do |f| %&amp;gt;
&amp;nbsp; &amp;lt;%= f.text_field :plate_no %&amp;gt;
&amp;nbsp; &amp;lt;%= select("truck", "company_id", Company.find(:all).collect {|c| [ c.name, c.id ] }, { :include_blank =&amp;gt; true }) %&amp;gt;
&amp;nbsp; &amp;lt;%= submit_tag 'Create' %&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;What we have is a text field for the truck's plate number and a select field for it's company. Except that there's no company yet to select, and even if there was, there's no way we can add another. And in the case of this project, it is a must that the user be able to easily add companies which the particular entity (truck, vessel, container, depot, cat, dog, fish) belongs to on the fly.&lt;br /&gt;
&lt;br /&gt;
We can of course add a link that gives the user an option to create a new company, but that will be an akward solution and would be inconvenient for the user at the very least. What we need is an unobstrusive way for the user to enter the t company, as well as a robust solution which we can easily adapt in code.&lt;br /&gt;
&lt;br /&gt;
For starters, let us try this: &lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;&amp;lt;% form_for :truck, @truck, :url =&amp;gt; { :action =&amp;gt; "create" } do |f| %&amp;gt;
&amp;nbsp; &amp;lt;%= f.text_field :plate_no %&amp;gt;
&amp;nbsp; &amp;lt;%= text_field_tag :company_name %&amp;gt;
&amp;nbsp; &amp;lt;%= submit_tag 'Create' %&amp;gt;
&amp;lt;% end %&amp;gt; 
&lt;/pre&gt;Then for our controller:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;def create 
&amp;nbsp; @truck = Truck.new

&amp;nbsp; company_name = params[:company_name]
&amp;nbsp; company = Company.find_by_name(company_name)
&amp;nbsp; company ||= Company.create(:name =&amp;gt; company_name)

&amp;nbsp; @truck.company = company
&amp;nbsp; @truck.update_attributes(params[:truck])
end
&lt;/pre&gt;Which has to be repeated for our update action, and ALL the other views. Unobstrusive: yes. Robust: no.&lt;br /&gt;
&lt;br /&gt;
This is where my &lt;a href="http://github.com/erolfornoles/acts_as_reference/tree/master"&gt;acts_as_reference&lt;/a&gt; plugin comes into play.&lt;br /&gt;
&lt;br /&gt;
Install it via git:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;git submodule add git://github.com/ErolFornoles/acts_as_reference.git vendor/plugins/acts_as_reference
&lt;/pre&gt;And then use it in code:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;class Company &amp;lt; ActiveRecord::Base
&amp;nbsp; acts_as_reference :name, :create =&amp;gt; true
end
&lt;/pre&gt;&lt;pre class="ruby" name="code"&gt;&amp;lt;% form_for :truck, @truck, :url =&amp;gt; { :action =&amp;gt; "create" } do |f| %&amp;gt;
&amp;nbsp; &amp;lt;%= f.text_field :plate_no %&amp;gt;
&amp;nbsp; &amp;lt;%= f.text_field :company %&amp;gt;
&amp;nbsp; &amp;lt;%= submit_tag 'Create' %&amp;gt;
&amp;lt;% end %&amp;gt; 
&lt;/pre&gt;&lt;pre class="ruby" name="code"&gt;def create
&amp;nbsp; @truck = Truck.new
&amp;nbsp; @truck.update_attributes(params[:truck])
end
&lt;/pre&gt;Just a one-liner addition to our reference model. Simpler view code compared to the first one which used a select tag. And just the normal, plain, bland controller. Notice that our company field is now a simple text field which, uhmmm, accepts text. Let's drop in a little &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; &lt;a href="http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/"&gt;Autocomplete&lt;/a&gt; goodness and a few CSS custom styling, and we'll come up with something like this:&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_0gReFQ9CunU/SKV6lIZvR3I/AAAAAAAAAAg/fv6kOWXqFCo/s1600-h/acts_as_reference_001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_0gReFQ9CunU/SKV6lIZvR3I/AAAAAAAAAAg/JPUdnQNXqXg/s320-R/acts_as_reference_001.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
The user can type a new company, or auto-completion can guide him/her to typing or selecting an existing one.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1878052100340831050-686700384909069254?l=erolfornoles.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/polymorphic_associations/~4/pKs2H4KzF4Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/686700384909069254/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://erolfornoles.blogspot.com/2008/08/plugin-actsasreference.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/686700384909069254?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/686700384909069254?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/polymorphic_associations/~3/pKs2H4KzF4Y/plugin-actsasreference.html" title="ActsAsReference: A convenient method of handling belongs_to associations in Rails" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14566455241213375471" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_0gReFQ9CunU/SKV6lIZvR3I/AAAAAAAAAAg/JPUdnQNXqXg/s72-Rc/acts_as_reference_001.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://erolfornoles.blogspot.com/2008/08/plugin-actsasreference.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMNRXk8fSp7ImA9WxdbF0w.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050.post-6366213509651110997</id><published>2008-08-14T19:02:00.000+08:00</published><updated>2008-08-14T19:31:34.775+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-14T19:31:34.775+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="text editor" /><title>Editra: A free lightweight cross-platform editor</title><content type="html">"&lt;a href="http://editra.org/"&gt;Editra&lt;/a&gt; is a multi-platform text editor with an implementation that focuses on creating  an easy to use interface and features that aid in code development. Currently it  supports syntax highlighting and variety of other useful features for over 60 programming languages."&lt;br /&gt;
&lt;br /&gt;
I've just started using this text editor for my Rails projects, and so far it looks promising. It's an improvement to &lt;a href="http://www.scintilla.org/SciTE.html"&gt;SciTe&lt;/a&gt; and it's faster than &lt;a href="http://www.jedit.org/"&gt;JEdit&lt;/a&gt; or any of the IDE's that I have tried, specifically &lt;a href="http://www.netbeans.org/"&gt;Netbeans&lt;/a&gt;, &lt;a href="http://www.aptana.com/rails"&gt;RadRails&lt;/a&gt; and &lt;a href="http://www.activestate.com/Products/komodo_ide/"&gt;Komodo&lt;/a&gt;. It also has a file-browser plugin which makes working with Rails projects manageable. Not to mention that it's totally free.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1878052100340831050-6366213509651110997?l=erolfornoles.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/polymorphic_associations/~4/d-IZ4rWBpww" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/6366213509651110997/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://erolfornoles.blogspot.com/2008/08/editra-free-lightweight-cross-platform.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/6366213509651110997?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/6366213509651110997?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/polymorphic_associations/~3/d-IZ4rWBpww/editra-free-lightweight-cross-platform.html" title="Editra: A free lightweight cross-platform editor" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14566455241213375471" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://erolfornoles.blogspot.com/2008/08/editra-free-lightweight-cross-platform.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYNR347fip7ImA9WxdbFko.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050.post-233987032714996764</id><published>2008-08-13T18:00:00.000+08:00</published><updated>2008-08-14T09:43:16.006+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-14T09:43:16.006+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Rails 2.1" /><category scheme="http://www.blogger.com/atom/ns#" term="ActiveRecord" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby on Rails" /><category scheme="http://www.blogger.com/atom/ns#" term="optimize" /><category scheme="http://www.blogger.com/atom/ns#" term="eager loading" /><title>Optimize eager loading in Rails 2.1 using reference indexes</title><content type="html">Rails 2.1 has a new eager loading scheme that works in a radically different way compared to previous versions. Instead of wrapping everything up in one humongous SQL statement composed of a complex and lengthy series of joins, the new mechanism breaks the eager loading call to multiple simple statements.&lt;br /&gt;
&lt;br /&gt;
Let's say that we have three models:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;class PetShop &amp;lt; ActiveRecord::Base
  has_many :dogs
end

class Dog &amp;lt; ActiveRecord::Base
  belongs_to :pet_shop
end

class Cats &amp;lt; ActiveRecord::Base
  belongs_to :pet_shop
end&lt;/pre&gt;In Rails 2.0, this:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;PetShop.find(:all, :include =&amp;gt; [:cats, :dogs])&lt;/pre&gt;Will yield this:&lt;br /&gt;
&lt;pre class="sql" name="code"&gt;SELECT `pet_shops`.`id` AS t0_r0, `pet_shops`.`name` AS t0_r1, `pet_shops`.`created_at` AS t0_r2, `pet_shops`.`updated_at` AS t0_r3, `dogs`.`id` AS t1_r0, `dogs`.`name` AS t1_r1, `dogs`.`pet_shop_id` AS t1_r2, `dogs`.`created_at` AS t1_r3, `dogs`.`updated_at` AS t1_r4, `cats`.`id` AS t2_r0, `cats`.`name` AS t2_r1, `cats`.`pet_shop_id` AS t2_r2, `cats`.`created_at` AS t2_r3, `cats`.`updated_at` AS t2_r4 FROM `pet_shops` LEFT OUTER JOIN `dogs` ON dogs.pet_shop_id = pet_shops.id LEFT OUTER JOIN `cats` ON cats.pet_shop_id = pet_shops.id;&lt;/pre&gt;WTF?!&lt;br /&gt;
&lt;br /&gt;
This is a cartesian join; if you had 100 petshops, with 100 dogs and 100 cats each, the number of rows returned will be 100 * 100 * 100 = 1,000,000. A million friggin' rows. Add another association, like say has_many :birds, and the count further skyrockets.&lt;br /&gt;
&lt;br /&gt;
In Rails 2.1, the same call will result to:&lt;br /&gt;
&lt;pre class="sql" name="code"&gt;SELECT * FROM `pet_shops`;
SELECT `dogs`.* FROM `dogs` WHERE (`dogs`.pet_shop_id IN (1,2,3,4,5,6,7,8,9,10));
SELECT `cats`.* FROM `cats` WHERE (`cats`.pet_shop_id IN (1,2,3,4,5,6,7,8,9,10));&lt;/pre&gt;Back to our assumption of having 100 petshops, with 100 dogs and 100 cats each. The number of rows returned is now 100 + 100(100) + 100(100) = 20,100.&lt;br /&gt;
&lt;br /&gt;
There were reports though - unconfirmed, since I could not find a concrete article in the intertubes - that MySQL was taking a hit CPU-wise because of the additional queries. I have a different hunch though.&lt;br /&gt;
&lt;br /&gt;
Assuming we had the "usual" migration:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;create_table :pet_shops do |t|
  t.string :name
  t.timestamps
end

create_table :cats do |t|
  t.string :name
  t.references :pet_shop
  t.timestamps
end

create_table :dogs do |t|
  t.string :name
  t.references :pet_shop
  t.timestamps
end&lt;/pre&gt;We can analyze the SQL statements generated by Rails 2.1's eager loading mechanism by using MySQL's EXPLAIN command. We will not attempt to analyze the first statement since it is basically a fetch all.&lt;br /&gt;
&lt;pre class="sql" name="code"&gt;EXPLAIN SELECT `dogs`.* FROM `dogs` WHERE (`dogs`.pet_shop_id IN (1,2,3,4,5,6,7,8,9,10));
EXPLAIN SELECT `cats`.* FROM `cats` WHERE (`cats`.pet_shop_id IN (1,2,3,4,5,6,7,8,9,10));&lt;/pre&gt;And here's what we got in return:&lt;br /&gt;
&lt;blockquote&gt;ALL - A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked const, and usually very bad in all other cases. Normally, you can avoid ALL by adding indexes that allow row retrieval from the table based on constant values or column values from earlier tables.&lt;/blockquote&gt;"Normally not good, and usually very bad in all other cases." The MySQL guys sure didn’t mince words &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/using-explain.html"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Let’s do what they suggested and add an index to our reference field:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;add_index :dogs, :petshop_id
add_index :cats, :petshop_id&lt;/pre&gt;Or if you’re using the &lt;a href="http://code.google.com/p/easier-indexes/"&gt;easier_indexes&lt;/a&gt; plugin, we can revise our migration:&lt;br /&gt;
&lt;pre class="ruby" name="code"&gt;create_table :cats do |t|
  t.string :name
  t.references :pet_shop, :index =&amp;gt; true
  t.timestamps
end

create_table :dogs do |t|
  t.string :name
  t.references :pet_shop, :index =&amp;gt; true
  t.timestamps
end &lt;/pre&gt;Running the same EXPLAIN command this time yields us with:&lt;br /&gt;
&lt;blockquote&gt;range - Only rows that are in a given range are retrieved, using an index to select the rows.&lt;/blockquote&gt;I'm too lazy to do a benchmark now, so let me know how this one works for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1878052100340831050-233987032714996764?l=erolfornoles.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/polymorphic_associations/~4/KzNVzKYSS6o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/233987032714996764/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://erolfornoles.blogspot.com/2008/08/optimize-eager-loading-in-rails-21.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/233987032714996764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/233987032714996764?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/polymorphic_associations/~3/KzNVzKYSS6o/optimize-eager-loading-in-rails-21.html" title="Optimize eager loading in Rails 2.1 using reference indexes" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14566455241213375471" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://erolfornoles.blogspot.com/2008/08/optimize-eager-loading-in-rails-21.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ANSXw-eSp7ImA9WxdbFk4.&quot;"><id>tag:blogger.com,1999:blog-1878052100340831050.post-3252538214325727041</id><published>2008-08-13T16:32:00.000+08:00</published><updated>2008-08-13T20:49:58.251+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-13T20:49:58.251+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="General" /><title>About</title><content type="html">This is my blog of assorted geekiness, mostly dealing with Ruby on Rails. Here I will write about hints, tips, tricks and hacks, as well as feature topics on how to get the most out of Ruby/Rails. I hope to meet people who have the same interests as me, specially those from the RoR community. If there's anything specific which you would like to ask or discuss, please leave a comment or contact me directly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1878052100340831050-3252538214325727041?l=erolfornoles.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/polymorphic_associations/~4/1mvIY7enHyI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://erolfornoles.blogspot.com/feeds/3252538214325727041/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://erolfornoles.blogspot.com/2008/08/about.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/3252538214325727041?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1878052100340831050/posts/default/3252538214325727041?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/polymorphic_associations/~3/1mvIY7enHyI/about.html" title="About" /><author><name>Erol</name><uri>http://www.blogger.com/profile/03118720503362414087</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14566455241213375471" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://erolfornoles.blogspot.com/2008/08/about.html</feedburner:origLink></entry></feed>
