<?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>Kickass Labs &#187; Rails</title>
	<atom:link href="http://www.kickasslabs.com/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kickasslabs.com</link>
	<description>We &#9829; code.</description>
	<lastBuildDate>Sun, 04 Jul 2010 03:00:07 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Rails Gotcha: ActiveRecord Caches Associated Records by Default</title>
		<link>http://www.kickasslabs.com/2009/04/23/rails-gotcha-activerecord-caches-associated-records-by-default/</link>
		<comments>http://www.kickasslabs.com/2009/04/23/rails-gotcha-activerecord-caches-associated-records-by-default/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 03:00:00 +0000</pubDate>
		<dc:creator>gabe</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=258</guid>
		<description><![CDATA[ActiveRecord will cache the results of association method calls by default, unless you tell it not to. 
(This applies to Rails 2.3.2 and perhaps earlier versions.)
From the documentation:

project.milestones             # fetches milestones from the database
project.milestones.size        # uses [...]]]></description>
			<content:encoded><![CDATA[<p><strong>ActiveRecord will cache the results of association method calls by default, unless you tell it not to. </strong></p>
<p>(This applies to Rails 2.3.2 and perhaps earlier versions.)</p>
<p>From <a href="http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html">the documentation:</a></p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">project.<span style="color:#9900CC;">milestones</span>             <span style="color:#008000; font-style:italic;"># fetches milestones from the database</span>
project.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">size</span>        <span style="color:#008000; font-style:italic;"># uses the milestone cache</span>
project.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">empty</span>?      <span style="color:#008000; font-style:italic;"># uses the milestone cache</span>
project.<span style="color:#9900CC;">milestones</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">size</span>  <span style="color:#008000; font-style:italic;"># fetches milestones from the database</span></pre></div></div>

<p>Normally, this is great.  However, if you&#8217;re not aware of this default caching, you might see some strange behavior in your app or tests and have no idea what&#8217;s going on.  This default caching behavior had me and Abel stumped until we read about it in the docs.</p>
<p>Working with the same concept as the example in the documentation, where a Project has many Milestones, here&#8217;s a more explicit example of the caching behavior in action:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">project_1 = Project.<span style="color:#9900CC;">find_by_id</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>  
project_2 = Project.<span style="color:#9900CC;">find_by_id</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>  
<span style="color:#008000; font-style:italic;"># Load the same Project into two variables</span>
&nbsp;
project_1.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">length</span>   
<span style="color:#008000; font-style:italic;"># - Hits the db's Milestones table.  </span>
<span style="color:#008000; font-style:italic;"># - Caches milestones object on project_1.</span>
<span style="color:#008000; font-style:italic;"># - Returns 0. </span>
&nbsp;
Milestone.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:project_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">1</span>, <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'New Milestone'</span><span style="color:#006600; font-weight:bold;">&#41;</span>  
<span style="color:#008000; font-style:italic;"># Adds a milestone to the project. </span>
<span style="color:#008000; font-style:italic;"># But we don't do it through the project_1.milestones association</span>
<span style="color:#008000; font-style:italic;"># because that _would_ update project_1.milestones's cached value</span>
&nbsp;
project_1.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">length</span>   
<span style="color:#008000; font-style:italic;"># Returns 0 (not 1, like you'd expect) </span>
<span style="color:#008000; font-style:italic;"># because project_1.milestones was cached when </span>
<span style="color:#008000; font-style:italic;"># previously requested above.</span>
&nbsp;
project_2.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">length</span>  
<span style="color:#008000; font-style:italic;"># Returns 1, because project_2.milestones </span>
<span style="color:#008000; font-style:italic;"># hasn't been requested/cached yet.</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># Note: project_2.milestones is </span>
<span style="color:#008000; font-style:italic;"># a COMPLETELY DIFFERENT IN-MEMORY OBJECT </span>
<span style="color:#008000; font-style:italic;"># than project_1.milestones.</span>
<span style="color:#008000; font-style:italic;"># Taking this point further, here's an explicit example:</span>
&nbsp;
project_2.<span style="color:#9900CC;">milestones</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> Milestone.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Another Milestone'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;"># Put another milestone on the project through </span>
<span style="color:#008000; font-style:italic;"># project_2's milestones association.</span>
&nbsp;
project_1.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">length</span>
<span style="color:#008000; font-style:italic;"># Still returns 0, because project_1 already cached it's copy of </span>
<span style="color:#008000; font-style:italic;"># the milestones association back when there were 0.</span>
&nbsp;
project_2.<span style="color:#9900CC;">milestones</span>.<span style="color:#9900CC;">length</span> 
<span style="color:#008000; font-style:italic;"># Now returns 2, because only project_2 knows about the new milestone.</span>
&nbsp;
project_1.<span style="color:#9900CC;">milestones</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">length</span>  
<span style="color:#008000; font-style:italic;"># Returns 2, because ActiveRecord updates the cache </span>
<span style="color:#008000; font-style:italic;"># when association(true) is present.</span></pre></div></div>

<p>Another funny something to note about the association caching behavior is that <strong>even when ActiveRecord uses a cached value, it still emits SQL to the log file</strong>.  So, don&#8217;t let that trip you up either.</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.kickasslabs.com%2F2009%2F04%2F23%2Frails-gotcha-activerecord-caches-associated-records-by-default%2F&amp;linkname=Rails%20Gotcha%3A%20ActiveRecord%20Caches%20Associated%20Records%20by%20Default"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2009/04/23/rails-gotcha-activerecord-caches-associated-records-by-default/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Quick Hits: Setting the User Agent Header in Webrat</title>
		<link>http://www.kickasslabs.com/2009/03/31/quick-hits-setting-the-user-agent-header-in-webrat/</link>
		<comments>http://www.kickasslabs.com/2009/03/31/quick-hits-setting-the-user-agent-header-in-webrat/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 16:35:51 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[webrat]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=248</guid>
		<description><![CDATA[If you&#8217;ve read the new PragProg beta e-book on RSpec, you may have read that you can set HTTP headers for your Webrat request like so:

Given /^I am browsing the site using Safari$/ do
  header &#34;User-Agent&#34; , &#34;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us)&#34;
end

Like me, you may have found out the hard [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve read the new <a href="http://pragprog.com/" title="Pragmatic Programmers" target="pragprog">PragProg</a> <a href="http://www.pragprog.com/titles/achbd/the-rspec-book" title="The RSpec Book beta ebook" target="pragprog">beta e-book on RSpec</a>, you may have read that you can set HTTP headers for your Webrat request like so:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Given <span style="color:#006600; font-weight:bold;">/</span>^I am browsing the site using Safari$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  header <span style="color:#996600;">&quot;User-Agent&quot;</span> , <span style="color:#996600;">&quot;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us)&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Like me, you may have found out the hard way that this doesn&#8217;t work.  Webrat does not automagically apply these new HTTP headers to your request &#8211; they certainly don&#8217;t make it to my controller.  What worked for me:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Given <span style="color:#006600; font-weight:bold;">/</span>^I am browsing the site using Safari$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  headers<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;User-Agent&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us)&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">When</span> <span style="color:#006600; font-weight:bold;">/</span>^I visit my precious site$<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  get <span style="color:#996600;">'/my/precious/path'</span>, my_query_string, headers
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>In the code above, <code>headers</code> is a method call that returns all the HTTP headers for your request.  Just tack <code>headers</code> on as the third argument of your request, and you&#8217;re good to go.</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.kickasslabs.com%2F2009%2F03%2F31%2Fquick-hits-setting-the-user-agent-header-in-webrat%2F&amp;linkname=Quick%20Hits%3A%20Setting%20the%20User%20Agent%20Header%20in%20Webrat"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2009/03/31/quick-hits-setting-the-user-agent-header-in-webrat/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Better Rails Searching with Named Scopes using Scope Builder</title>
		<link>http://www.kickasslabs.com/2008/12/22/better-rails-searching-with-named-scopes-using-scope-builder/</link>
		<comments>http://www.kickasslabs.com/2008/12/22/better-rails-searching-with-named-scopes-using-scope-builder/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 19:54:16 +0000</pubDate>
		<dc:creator>gabe</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[named scope]]></category>
		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=109</guid>
		<description><![CDATA[When it comes writing elegant search code in a Rails app, Named Scopes immediately come to mind.  And for good reason: they&#8217;re a fantastic way to express, well, scopes, for your searches.  In your Person model, you might have named scopes like by_last_name, by_age, and by_sex.  But, what do you do when you want to [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes writing elegant search code in a Rails app, Named Scopes immediately come to mind.  And for good reason: they&#8217;re a fantastic way to express, well, scopes, for your searches.  In your Person model, you might have named scopes like <code>by_last_name</code>, <code>by_age</code>, and <code>by_sex</code>.  But, what do you do when you want to give your users a search form and let them find people by any combination of last name, age, and sex?</p>
<p><span id="more-109"></span></p>
<p>Well, you might try something like executing each named scope that you have params for and find the intersection of the IDs of all people returned from each named_scope.  That might look something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">p1 = Person.<span style="color:#9900CC;">by_last_name</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>
p2 = Person.<span style="color:#9900CC;">by_age</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span>
p3 = Person.<span style="color:#9900CC;">by_sex</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:sex</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:sex</span><span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
people <span style="color:#006600; font-weight:bold;">+</span>= p1 <span style="color:#9966CC; font-weight:bold;">if</span> p1.<span style="color:#9900CC;">length</span> <span style="color:#006600; font-weight:bold;">+</span> p2 <span style="color:#006600; font-weight:bold;">+</span> p3</pre></div></div>

<p>What you really want is <a href="http://github.com/ryanb/scope-builder/tree/master">Ryan Bates&#8217; Scope Builder gem</a>.</p>
<p>Scope Builder lets you &#8220;build up named scopes conditionally.&#8221;  From the README:</p>
<blockquote><p>This gem adds the scope_builder method to all Active Record models. A<br />
builder behaves exactly like any other named scope except that calling<br />
other named scopes on it will alter the builder itself rather than<br />
returning a new named scope.</p></blockquote>
<p>Here&#8217;s some example code using that defines Person.search using named scopes for last_name, age, and sex:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Person <span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  named_scope <span style="color:#ff3333; font-weight:bold;">:by_last_name</span>, <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>last_name<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:conditions</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'last_name = :last_name'</span>,
        <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:last_name</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; last_name <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span> 
&nbsp;
  named_scope <span style="color:#ff3333; font-weight:bold;">:by_age</span>, <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>age<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:conditions</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'age = :age'</span>,
        <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:age</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; age <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span> 
&nbsp;
  named_scope <span style="color:#ff3333; font-weight:bold;">:by_sex</span>, <span style="color:#CC0066; font-weight:bold;">lambda</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>sex<span style="color:#006600; font-weight:bold;">|</span>
    <span style="color:#006600; font-weight:bold;">&#123;</span>
      <span style="color:#ff3333; font-weight:bold;">:conditions</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'sex = :sex'</span>,
        <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:sex</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; sex <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#006600; font-weight:bold;">&#125;</span>
  <span style="color:#006600; font-weight:bold;">&#125;</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#41;</span>
    scope_builder <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>builder<span style="color:#006600; font-weight:bold;">|</span>
      builder.<span style="color:#9900CC;">by_last_name</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      builder.<span style="color:#9900CC;">by_age</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:age</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      builder.<span style="color:#9900CC;">by_sex</span><span style="color:#006600; font-weight:bold;">&#40;</span>options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:sex</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> options<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:sex</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>So, now all you need is a People Search form and an action to handle finding the right people.  Here&#8217;s what your search action might look like inside PeopleController:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> search
  <span style="color:#0066ff; font-weight:bold;">@people</span> = Person.<span style="color:#9900CC;">search</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">all</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Important note: When using ScopeBuilder as shown above, you&#8217;ll have to call <code>#all</code> because, in this case, <code>Person.search</code> returns a ScopeBuilder object, not a collection of ActiveRecord Person objects.  To get at the people collection, you call <code>#all</code> on the ScopeBuilder object returned by <code>Person.search</code>.</p>
<p>So, see?  Isn&#8217;t that pretty?  You&#8217;ve got a simple search that will find all the people that meet any all of the attributes passed in from the search form.  Ta da!</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.kickasslabs.com%2F2008%2F12%2F22%2Fbetter-rails-searching-with-named-scopes-using-scope-builder%2F&amp;linkname=Better%20Rails%20Searching%20with%20Named%20Scopes%20using%20Scope%20Builder"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2008/12/22/better-rails-searching-with-named-scopes-using-scope-builder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick and Dirty Messaging</title>
		<link>http://www.kickasslabs.com/2008/11/22/93/</link>
		<comments>http://www.kickasslabs.com/2008/11/22/93/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 20:05:55 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Great Minds]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[gm]]></category>
		<category><![CDATA[message queue]]></category>
		<category><![CDATA[messaging]]></category>
		<category><![CDATA[rails rumble]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[rumble]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=93</guid>
		<description><![CDATA[Our Rails Rumble 2008 entry, Great Minds (you can have a look at the latest version or the original Rumble version), required a messaging system.  Such systems are easy to do wrong, and we knew we&#8217;d need something that would stay solid under unknown load during Rumble judging.
The solution was quick &#38; dirty (as [...]]]></description>
			<content:encoded><![CDATA[<p>Our <a href="http://railsrumble.com/" title="Rails Rumble 2008" target="rr2008">Rails Rumble 2008</a> entry, <i>Great Minds</i> (you can have a look at the <a href="http://greatminds.kickasslabs.com/" title="Great Minds" target="gmkal">latest version</a> or the <a href="http://greatminds.r08.railsrumble.com/" title="Great Minds - Rumble Version" target="gmrr">original Rumble version</a>), required a messaging system.  Such systems are easy to do wrong, and we knew we&#8217;d need something that would stay solid under unknown load during Rumble judging.</p>
<p>The solution was quick &amp; dirty (as most solutions are during Rails Rumble), but the results worked, and allowed us to qualify for judging and reach a respectable 28th place finish in the &#8220;Completeness&#8221; category.</p>
<p>Check out the details after the fold.</p>
<p><span id="more-93"></span></p>
<h3>Design Constraints</h3>
<p><i>Great Minds</i> is a word game played by 2 or more players.  The game is played in a virtual chat <b>Room</b>, containing one or more <b>Players.</b>  Players can take various actions, such as submitting a word to the game, chatting, or changing their handle/username.  The results of these actions must be transmitted to other players in the room.</p>
<p>Other constraints on the design included:</p>
<ul>
<li><b>No New Technologies:</b>  There are tools like <a href="http://juggernaut.rubyforge.org/" title="Juggernaut" target="juggernaut">Juggernaut</a> that make messaging pretty easy, but we had no hands-on experience with them, and learning a new tool on a 48-hour schedule was deemed a risk to completing the project &#038; qualifying for Rumble judging.</li>
<li><b>Broadcast:</b>  We needed something more than a simple message queue like <a href="http://xph.us/software/beanstalkd/" title="Beanstalk" target="beanstalk">Beanstalk</a>; the consumer of a message couldn&#8217;t remove it from the queue, as there might be other consumers needing the same message.</li>
<li><b>Room State Reconstruction:</b>  Someone coming to the room for the first time (or leaving and returning) should be able to see the current room state, including all participants, recently played words, and recent chat.</li>
<li><b>Replay:</b>  Though we didn&#8217;t get around to implementing it, we wanted to offer the ability to review a particularly funny game.</li>
</ul>
<p>The first two constraints affected our design and technology choices; the second two demanded that the messages be persisted.  (Alternatively, we could have saved the room state in some other way, but as long as we had the messages anyway, it seemed simpler to just keep them and reconstruct the state.)</p>
<h3>Client Implementation</h3>
<p>In the absence of a viable push solution like Juggernaut, we opted for a polling solution:  Clients would periodically send a signal that:</p>
<ul>
<li>let the server know they&#8217;re still alive and connected,</li>
<li>sent any new messages to the server, and</li>
<li>requested any pending messages from the server.</li>
</ul>
<p>On the client side, this meant that every message got packaged as JSON, stuck in a queue, and periodically collected and sent to the server as the optional payload of a keep-alive signal.  With some help from Prototype, this was as simple as:</p>
<pre>
  function SyncMessages() {
          var data = Object.toJSON(MESSAGES_QUEUE);
          var url = '/room/sync_messages';
          var params = {
                  authenticity_token: AUTH_TOKEN,
                  messages: '[]',
                  //messages: Object.toJSON(MESSAGES_QUEUE),
                  last_message_id: LAST_MESSAGE_ID };

          new Ajax.Request(url, {
            method: 'post',
                  parameters: params,
            onSuccess: HandleMessages });
  }

  SyncMessages(); //start first on load
  var message_syncer = new PeriodicalExecuter(SyncMessages, 3);
</pre>
<p><code>HandleMessages()</code> updates the DOM based on messages coming back.</p>
<p>The other feature to note is the <code>LAST_MESSAGE_ID</code> token above.  Each client is responsible for keeping track of the last message ID it got.  On the server side, message IDs are assigned sequentially, so all new messages are guaranteed to have a higher ID.</p>
<p>We could have kept track of each client&#8217;s last message on the server side, but this would have been much more complex &#8211; we would have needed to store data either in the session (which already held a fair amount of stuff) or in another table in order to keep track of who had received what.</p>
<h3>Server Implementation</h3>
<p>On the server side, messages were persisted in a table.  This table would have relatively frequent inserts, somewhat more frequent reads, and no updates or deletions.  For this reason, we went with the default MyISAM table architecture.  (We had considered a design that would have updated the table with delivery status information and would have required InnoDB&#8217;s row-level locking, but in the end we opted for the simpler design.)  The table looks like:</p>
<pre>
  class CreateMessages < ActiveRecord::Migration
    def self.up
      create_table :messages do |t|
        t.integer :message_type_id, :room_id, :game_id, :user_id
        t.string  :data, :user_handle
        t.timestamps
      end
    end

    def self.down
      drop_table :messages
    end
  end
</pre>
<p>It also has an index:</p>
<pre>
  class AddRoomIndexToMessages < ActiveRecord::Migration
    def self.up
      add_index :messages, [:room_id, :id]
    end

    def self.down
      remove_index :messages, [:room_id, :id]
    end
  end
</pre>
<p>Recall that the client keeps track of the last message it got, and periodically requests all messages since.  This index speeds that request - which is just <code>msgs = Message.find :all, :conditions => ['room_id = ? AND id > ?', session['room_id'], last_message_id], <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder => 'id'</code>.  (Yes, I know that should be a <a href="http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know" title="Named Scopes" title="namedscopes">named scope</a>.  I hadn't gotten around to learning those yet at the time of the Rumble.)</p>
<p>When the a keep-alive signal hits the server:</p>
<ul>
<li>any new messages attached to the signal are added to the <code>messages</code> table,</li>
<li>any game mechanics related to those messages are executed (which may result in more messages being added to the table), and</li>
<li>all messages for the caller's room with an ID greater than the caller's LAST_MESSAGE_ID are packaged as JSON and sent back down in the HTTP response.</li>
</ul>
<p>A note:  If you're in a room and you enter (for example) a chat message, there's actually a server round-trip involved (pushing the message to the server and getting the same message back as a response) before that chat message is shown in your browser.  We worried about this, but not for long - the interactivity delay turned out to be minimal, and it was much simpler to keep it this way (every message is treated the same for all clients) than to create an exception (you update your DOM with your chat messages immediately, but your own chat messages are somehow filtered from your message stream).</p>
<h3>What's Missing?</h3>
<p>Obviously, this was a quick &amp; dirty solution, tailored to the immediate needs of a Rails Rumble project.  Here's what I'd do differently (and indeed, will do differently, as we have plans for the future of Great Minds - stay tuned):</p>
<ul>
<li><b>Security:</b>  We do use the Rails session <code>authenticity_token</code>, but there's still no protection from a server flood from someone who has a token, either by cranking down the polling interval or by fiddling with the LAST_MESSAGE_ID.</li>
<li><b>Server Push:</b>  Polling is wasteful - requests are made whether or not there are any messages to send or receive.  We plan to move to Juggernaut soon.</li>
<li><b>Decoupling from Game Mechanics:</b>  In the first iteration, message receipt and delivery were too intimately tied to game mechanics, with <code>Message</code> objects being explictly constructed and followed by <code>Message.save!</code> calls.  I've already started the process of teasing them apart in preparation for the move to Juggernaut, factoring this into a <code>deliver_message()</code> method.</li>
</ul>
<p>Questions?  Thoughts?  Add a comment!  I promise to get back to you.</p>
<p><a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fwww.kickasslabs.com%2F2008%2F11%2F22%2F93%2F&amp;linkname=Quick%20and%20Dirty%20Messaging"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2008/11/22/93/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
