<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Snow Giraffe Tech &#187; ActiveRecordContext</title>
	<atom:link href="http://www.snowgiraffe.com/tech/tag/activerecordcontext/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.snowgiraffe.com/tech</link>
	<description>rails, rubies, and sometimes dolphins</description>
	<lastBuildDate>Mon, 07 Jun 2010 14:36:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>When to :select and :include your rubies and rails</title>
		<link>http://www.snowgiraffe.com/tech/327/when-to-select-and-include-your-rubies-and-rails/</link>
		<comments>http://www.snowgiraffe.com/tech/327/when-to-select-and-include-your-rubies-and-rails/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 21:16:41 +0000</pubDate>
		<dc:creator>blythe</dc:creator>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[:include]]></category>
		<category><![CDATA[:select]]></category>
		<category><![CDATA[ActiveRecordContext]]></category>
		<category><![CDATA[eager loading]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.snowgiraffe.com/tech/?p=327</guid>
		<description><![CDATA[Although plugins exist to force :select and :include to play nice with ActiveRecord::Base.find, using this approach does not always yield the best performance. The post discusses when to use eager loading and when to use other approaches and the plugins that will help you.]]></description>
			<content:encoded><![CDATA[<div id="attachment_354" class="wp-caption alignleft" style="width: 160px"><img class="size-thumbnail wp-image-354" title="Finger Monkey" src="http://www.snowgiraffe.com/tech/wp-content/uploads/2009/04/mini-monkey-3-150x150.jpg" alt="Every blog post could use a finger monkey" width="150" height="150" /><p class="wp-caption-text">Every blog post could use a finger monkey</p></div>
<p>The vanilla rails ActiveRecord finders do not allow us to specify the <span class="inline_code">:select</span> clause when associations are eager loaded with the <span class="inline_code">:include</span> option. There has been <a href="http://dev.rubyonrails.org/ticket/5371">ticket</a> after <a href="http://dev.rubyonrails.org/attachment/ticket/7147/options_select_working_with_eager_loading.diff" target="_blank">ticket</a> on the rails site the proposed  patches were rejected on the grounds that an alternative, such as <a href="http://svn.techno-weenie.net/projects/plugins/active_record_context/README">ActiveRecordContext</a> (a fantasic plugin by the way) should be used instead.<br />
From the database perspective, selecting fewer columns can give  huge performance boosts in some situations especially when the selected fields are indexed. However, often when joined tables are sparse (many base table records are pointing to the same joined table records), you might be better off running two queries: one on the base table, followed by a second on the join table with the collected foreign keys. To illustrate this, an employee has a fairly unique address while she shares her position in the company with several others.</p>
<pre class="ruby"><span class="constant">Employee</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span><span class="punct">,</span> <span class="symbol">:include</span> <span class="punct">=&gt;</span> <span class="symbol">:position</span></pre>
<p>would probably be less efficient than</p>
<pre class="ruby"><span class="ident">employees</span> <span class="punct">=</span> <span class="constant">Employee</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span>

<span class="ident">positions</span> <span class="punct">=</span> <span class="constant">Positions</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span><span class="punct">,</span> <span class="symbol">:conditions</span> <span class="punct">=&gt;</span> <span class="punct">['</span><span class="string">id in (?)</span><span class="punct">',</span> <span class="ident">employees</span><span class="punct">.</span><span class="ident">collect</span><span class="punct">(&amp;</span><span class="symbol">:id</span><span class="punct">)]</span>

<span class="ident">employees</span><span class="punct">.</span><span class="ident">each</span><span class="punct">{|</span><span class="ident">employee</span><span class="punct">|</span> <span class="ident">employee</span><span class="punct">.</span><span class="ident">position</span> <span class="punct">=</span> <span class="ident">positions</span><span class="punct">.</span><span class="ident">select</span> <span class="punct">{|</span><span class="ident">p</span><span class="punct">|</span> <span class="ident">p</span><span class="punct">.</span><span class="ident">to_param</span> <span class="punct">==</span> <span class="ident">employee</span><span class="punct">.</span><span class="ident">posistion_id</span><span class="punct">}</span></pre>
<p>This is exactly what <a href="http://svn.techno-weenie.net/projects/plugins/active_record_context/README">active record context </a>does but without the messy details. In addition, the records are cached so any subsequent references to the associations hit the cache instead of rerunning a query.</p>
<p><span id="more-327"></span></p>
<pre class="ruby"><span class="ident">employees</span> <span class="punct">=</span> <span class="constant">Employee</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span>
<span class="constant">Positions</span><span class="punct">.</span><span class="ident">preload</span><span class="punct">(</span><span class="ident">employees</span><span class="punct">)</span></pre>
<p>On the other hand, provided that a reasonable number of records are queried, including the address would probably be more efficient.</p>
<pre class="ruby"><span class="constant">Employee</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span><span class="punct">,</span> <span class="symbol">:include</span> <span class="punct">=&gt;</span> <span class="symbol">:address</span><span class="punct">,</span> <span class="symbol">:select</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">addresses.city, employees.*</span><span class="punct">'</span></pre>
<p>In this case wouldn&#8217;t it be great to use a <span class="inline_code">:select</span> clause if for instance you were only interested in for instance the city. To achieve this, I updated the <a href="http://www.snowgiraffe.com/tech/?p=329" target="_self">eload select plugin</a>. It does use some tricky parsing but does have the advantage of accepting aliases and allowing you to select from the base table (some alternates include all base columns).</p>
<p>One disadvantage of using <span class="inline_code">:select</span> is a lot of overhead is spent in rails on aliasing columns. Its really nasty in there and probably the reason that <span class="inline_code">:select</span> is not supported with <span class="inline_code">:include</span> out of the box.</p>
<p>If you really are having performance issues, its probably best to abandon the <span class="inline_code">:include</span> altogether and rewrite it as a :join.</p>
<pre class="ruby"><span class="ident">employees</span> <span class="punct">=</span> <span class="constant">Employee</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span><span class="punct">,</span> <span class="symbol">:select</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">addresses.city as address_city, employees.*</span><span class="punct">',</span>

<span class="symbol">:joins</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">left outer join addresses on addresses.id = employees.address_id</span><span class="punct">'</span>

<span class="ident">employees</span><span class="punct">.</span><span class="ident">first</span><span class="punct">['</span><span class="string">address_city</span><span class="punct">']</span></pre>
<p><img class="alignright size-thumbnail wp-image-356" title="piggy" src="http://www.snowgiraffe.com/tech/wp-content/uploads/2009/04/piggy-150x150.jpg" alt="piggy" width="150" height="150" />Stefan Kaes has written an excellent plugin called <a title="piggy back plugin" href="http://railsexpress.de/svn/plugins/piggy_back/trunk/README" target="_blank">piggy back</a> that does this for you with <span class="inline_code">belongs_to</span> and <span class="inline_code">has_one</span> relationships. For common delegated fields, this plugin is a winner.</p>
<pre class="ruby"><span class="constant">Employees</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:all</span><span class="punct">,</span> <span class="symbol">:piggy</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">address_city</span><span class="punct">'</span>

<span class="ident">employees</span><span class="punct">.</span><span class="ident">first</span><span class="punct">.</span><span class="ident">address_city</span></pre>
<p>So in conclusion, install <a href="http://www.snowgiraffe.com/tech/?p=329">eload-select plugin </a>and you get <span class="inline_code">:select</span> and <span class="inline_code">:include</span> playing happily together. However, sometimes its not the best option out there. There is a huge open source toolbox. Use them wisely.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.snowgiraffe.com/tech/327/when-to-select-and-include-your-rubies-and-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
