<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Gray Soft / Rails / Five ActiveRecord Tips</title>
  <id>tag:graysoftinc.com,2014-03-20:/posts/49</id>
  <updated>2014-03-27T01:38:28Z</updated>
  <link rel="self" href="http://graysoftinc.com/rails/five-activerecord-tips/feed.xml"/>
  <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips"/>
  <author>
    <name>James Edward Gray II</name>
  </author>
  <entry>
    <title>The 11th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_457"/>
    <id>tag:graysoftinc.com,2011-08-24:/comments/457</id>
    <updated>2014-03-27T01:38:28Z</updated>
    <summary>Thanks for the duplicate tip.</summary>
    <content type="html">&lt;p&gt;Thanks for the duplicate tip.&lt;/p&gt;</content>
    <author>
      <name>roger</name>
    </author>
  </entry>
  <entry>
    <title>The 10th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_259"/>
    <id>tag:graysoftinc.com,2009-02-09:/comments/259</id>
    <updated>2014-04-10T21:19:41Z</updated>
    <summary>Sadly apparently no one in the Rails community is aware of your first topic. But even more sadly your solution actually features a race condition similar to that in the original implementation; namely two competing processes might run in the situa...</summary>
    <content type="html">&lt;p&gt;Sadly apparently no one in the Rails community is aware of your first topic. But even more sadly your solution actually features a race condition similar to that in the original implementation; namely two competing processes might run in the situation where the entry is not yet there. The only way I found to work around that and any those issues is by using some kind of DB level locking, see &lt;a href="http://1rad.wordpress.com/2008/09/29/0x04-atomic-science/"&gt;http://1rad.wordpress.com/2008/09/29/0x04-atomic-science/&lt;/a&gt; I would like to see a MT safe implementation in rails, but apparently no one cares.&lt;/p&gt;</content>
    <author>
      <name>eno</name>
    </author>
  </entry>
  <entry>
    <title>The 9th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_200"/>
    <id>tag:graysoftinc.com,2008-09-19:/comments/200</id>
    <updated>2014-04-10T21:18:08Z</updated>
    <summary>Technically, your fourth tip is wrong.  `#find` is for finding records, but you&amp;#39;re running an aggregated query.  That&amp;#39;s what `#count` was made for.  However, you can&amp;#39;t perform multiple aggregations (if someone can suggest a clean API for this, I&amp;#39;d...</summary>
    <content type="html">&lt;p&gt;Technically, your fourth tip is wrong.  &lt;code&gt;#find&lt;/code&gt; is for finding records, but you're running an aggregated query.  That's what &lt;code&gt;#count&lt;/code&gt; was made for.  However, you can't perform multiple aggregations (if someone can suggest a clean API for this, I'd be more then happy to implement).&lt;/p&gt;

&lt;p&gt;However, #5 can be shortened to: &lt;code&gt;User.count(:id, :group =&amp;gt; :email, :having =&amp;gt; 'count(id) &amp;gt; 1')&lt;/code&gt;.  As a bonus, you can use a &lt;code&gt;belongs_to&lt;/code&gt; attribute.  &lt;code&gt;Order.count(:id, :group =&amp;gt; :product)&lt;/code&gt;.  For cases where you can't use &lt;code&gt;#count&lt;/code&gt;, you can also do something like:  &lt;code&gt;User.connection.select_all(User.sanitize_sql([..., *args]))&lt;/code&gt;.  It's definitely not pretty, so perhaps creating pseudo models with your custom #find call isn't a big deal.&lt;/p&gt;

&lt;p&gt;Just FYI: surround source code terms like &lt;code&gt;foo_bar&lt;/code&gt; with the tilde so that markdown doesn't treat it like &lt;em&gt;italics&lt;/em&gt;.&lt;/p&gt;</content>
    <author>
      <name>rick</name>
    </author>
  </entry>
  <entry>
    <title>The 8th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_199"/>
    <id>tag:graysoftinc.com,2008-08-22:/comments/199</id>
    <updated>2014-04-10T21:15:46Z</updated>
    <summary>Thanks so much for that!</summary>
    <content type="html">&lt;p&gt;Thanks so much for that!&lt;/p&gt;</content>
    <author>
      <name>Alex</name>
    </author>
  </entry>
  <entry>
    <title>The 7th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_198"/>
    <id>tag:graysoftinc.com,2008-08-21:/comments/198</id>
    <updated>2014-04-10T21:15:46Z</updated>
    <summary>Sure, you use it like this:

```ruby
People.find_all_in_chunks(:per_page =&amp;gt; 200) do |person|
  # … use person here …
end
```

I wasn&amp;#39;t aware of `paginated_each()` when I wrote it though.  You can just use that with a recent version of `wil...</summary>
    <content type="html">&lt;p&gt;Sure, you use it like this:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="no"&gt;People&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all_in_chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:per_page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# … use person here …&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I wasn't aware of &lt;code&gt;paginated_each()&lt;/code&gt; when I wrote it though.  You can just use that with a recent version of &lt;code&gt;will_paginate&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="no"&gt;People&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;paginated_each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:per_page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# … use person here …&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hope that helps.&lt;/p&gt;</content>
    <author>
      <name>James Edward Gray II</name>
    </author>
  </entry>
  <entry>
    <title>The 6th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_197"/>
    <id>tag:graysoftinc.com,2008-08-21:/comments/197</id>
    <updated>2014-04-10T21:15:46Z</updated>
    <summary>Any chance you would mind sharing a syntactically correct example of usage for `find_all_in_chunks`?  I&amp;#39;m kind of a noob and can&amp;#39;t figure out how to use it to replace `find(:all).each`…</summary>
    <content type="html">&lt;p&gt;Any chance you would mind sharing a syntactically correct example of usage for &lt;code&gt;find_all_in_chunks&lt;/code&gt;?  I'm kind of a noob and can't figure out how to use it to replace &lt;code&gt;find(:all).each&lt;/code&gt;…&lt;/p&gt;</content>
    <author>
      <name>Alex</name>
    </author>
  </entry>
  <entry>
    <title>The 5th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_195"/>
    <id>tag:graysoftinc.com,2008-07-27:/comments/195</id>
    <updated>2014-04-10T21:12:13Z</updated>
    <summary>Tips 4 &amp;amp; 5 were a big help. BTW

&amp;gt; I don&amp;#39;t recall ever using `HAVING` without `GROUP BY`, though there probably are some cases where it would make sense to do so.

I suppose that would just be a `where` clause.  </summary>
    <content type="html">&lt;p&gt;Tips 4 &amp;amp; 5 were a big help. BTW&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I don't recall ever using &lt;code&gt;HAVING&lt;/code&gt; without &lt;code&gt;GROUP BY&lt;/code&gt;, though there probably are some cases where it would make sense to do so.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I suppose that would just be a &lt;code&gt;where&lt;/code&gt; clause.  &lt;/p&gt;</content>
    <author>
      <name>Paul Grout</name>
    </author>
  </entry>
  <entry>
    <title>The 4th Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_184"/>
    <id>tag:graysoftinc.com,2008-05-13:/comments/184</id>
    <updated>2014-04-10T21:10:31Z</updated>
    <summary>I was using an older copy of `will_paginate` that didn&amp;#39;t yet contain `paginated_each`.  Thanks for pointing it out to me.</summary>
    <content type="html">&lt;p&gt;I was using an older copy of &lt;code&gt;will_paginate&lt;/code&gt; that didn't yet contain &lt;code&gt;paginated_each&lt;/code&gt;.  Thanks for pointing it out to me.&lt;/p&gt;</content>
    <author>
      <name>James Edward Gray II</name>
    </author>
  </entry>
  <entry>
    <title>The 3rd Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_183"/>
    <id>tag:graysoftinc.com,2008-05-13:/comments/183</id>
    <updated>2014-04-10T21:10:31Z</updated>
    <summary>`will_paginate` actually includes a [paginated_each](http://github.com/mislav/will_paginate/tree/master/lib/will_paginate/finder.rb#L99-112) method which does operate on batched groups of AR models.

Very important when your set is large.

Nic...</summary>
    <content type="html">&lt;p&gt;&lt;code&gt;will_paginate&lt;/code&gt; actually includes a &lt;a href="http://github.com/mislav/will_paginate/tree/master/lib/will_paginate/finder.rb#L99-112"&gt;paginated_each&lt;/a&gt; method which does operate on batched groups of AR models.&lt;/p&gt;

&lt;p&gt;Very important when your set is large.&lt;/p&gt;

&lt;p&gt;Nice tip on the &lt;code&gt;HAVING&lt;/code&gt; clause.&lt;/p&gt;

&lt;p&gt;Also, I haven't played with it much, but you could probably add db-computed attributes to an &lt;code&gt;ActiveRecord&lt;/code&gt; model through options specified in a &lt;code&gt;named_scope&lt;/code&gt;.&lt;/p&gt;</content>
    <author>
      <name>Duncan Beevers</name>
    </author>
  </entry>
  <entry>
    <title>The 2nd Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_182"/>
    <id>tag:graysoftinc.com,2008-04-14:/comments/182</id>
    <updated>2014-03-27T01:38:25Z</updated>
    <summary>Useful knowledge.  Thanks for writing up these tips.</summary>
    <content type="html">&lt;p&gt;Useful knowledge.  Thanks for writing up these tips.&lt;/p&gt;</content>
    <author>
      <name>Andy Stewart</name>
    </author>
  </entry>
  <entry>
    <title>The 1st Comment on "Five ActiveRecord Tips"</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips#comment_181"/>
    <id>tag:graysoftinc.com,2008-04-11:/comments/181</id>
    <updated>2014-03-27T01:38:25Z</updated>
    <summary>I have a strong feeling that you are going to be a winner!

Thank you so much for the tips (especially for #2).</summary>
    <content type="html">&lt;p&gt;I have a strong feeling that you are going to be a winner!&lt;/p&gt;

&lt;p&gt;Thank you so much for the tips (especially for #2).&lt;/p&gt;</content>
    <author>
      <name>Semin</name>
    </author>
  </entry>
  <entry>
    <title>Five ActiveRecord Tips</title>
    <link rel="alternate" href="http://graysoftinc.com/rails/five-activerecord-tips"/>
    <id>tag:graysoftinc.com,2008-04-10:/posts/49</id>
    <updated>2014-04-10T21:19:41Z</updated>
    <summary>Here's my best effort at showing some ActiveRecord voodoo.</summary>
    <content type="html">&lt;p&gt;This article was written for the &lt;a href="http://railscasts.com/contest"&gt;Railcasts 100th Episode Contest&lt;/a&gt;.  I think the idea is great and I look forward to reading great tips from all who decide to participate.&lt;/p&gt;

&lt;h4&gt;1. &lt;code&gt;create_or_find_by_…&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;I imagine most of you know that &lt;code&gt;ActiveRecord&lt;/code&gt; can handle finders like:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="no"&gt;MyARClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_or_create_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will attempt to find the object that has &lt;code&gt;some_name&lt;/code&gt; in its &lt;code&gt;name&lt;/code&gt; field or, if the find fails, a new object will be created with that &lt;code&gt;name&lt;/code&gt;.  It's important to note that the order is exactly as I just listed it:  find then create.  Here are the relevant lines from the current Rails source showing the process:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;find_initial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nil?&lt;/span&gt;
  &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:attributes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;guard_protected_attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;#{'yield(record) if block_given?'}&lt;/span&gt;
  &lt;span class="c1"&gt;#{'record.save' if instantiator == :create}&lt;/span&gt;
  &lt;span class="n"&gt;record&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="n"&gt;record&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code is inside a &lt;code&gt;String&lt;/code&gt; literal fed to &lt;code&gt;class_eval()&lt;/code&gt;, which is why you see interpolation being used.&lt;/p&gt;

&lt;p&gt;Unfortunately, this process is subject to race conditions because the object could be created by another process (or &lt;code&gt;Thread&lt;/code&gt;) between the find and the creation.  If that happens, you are likely to run into another hardship in that calls to &lt;code&gt;create()&lt;/code&gt; fail quietly (returning the unsaved object).  These are some pretty rare happenings for sure, but they can be avoided under certain conditions.&lt;/p&gt;

&lt;p&gt;I find myself typically using &lt;code&gt;find_or_create_by_…&lt;/code&gt; for things like category groupings or geocoded locations.  In my case, there always seems to be two unique properties I can count on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don't allow duplicate listings&lt;/li&gt;
&lt;li&gt;I don't have to worry about entries being deleted from the database&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;When both of those conditions are true, you can rewrite the Rails helper method to be multiprocessing safe.  The steps are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build validations so that attempts to save the duplicate fail&lt;/li&gt;
&lt;li&gt;Be sure to use &lt;code&gt;create!()&lt;/code&gt; instead of &lt;code&gt;create()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Reverse the order to &lt;code&gt;create!()&lt;/code&gt; then &lt;code&gt;find()&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Here's the practical example of how this plays out:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;validates_uniqueness_of&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_or_find_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="n"&gt;find_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The idea here is that we try the &lt;code&gt;create!()&lt;/code&gt; first and just let it fail if it doesn't validate (because it is a duplicate).  I use &lt;code&gt;create!()&lt;/code&gt; because it doesn't fail silently and the truth is that I generally prefer it for that very reason.  You could also use &lt;code&gt;create()&lt;/code&gt; and check the returned object with &lt;code&gt;new_record?()&lt;/code&gt;, if you prefer.  When the &lt;code&gt;create!()&lt;/code&gt; fails, we know it's safe to call the finder because there is definitely a matching entry in the database.&lt;/p&gt;

&lt;h4&gt;2. &lt;code&gt;find_all_in_chunks&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;I often want to scan whole tables in a Rails application, usually to generate reports about the data.  Of course, for very large tables, a call to &lt;code&gt;find(:all)&lt;/code&gt; is not generally a great idea as it uses up too much memory to slurp all of that data into Ruby objects.&lt;/p&gt;

&lt;p&gt;I have a tiny little library I drop in most Rails projects now to help with this.  It requires &lt;a href="http://github.com/mislav/will_paginate/tree/master"&gt;will_paginate&lt;/a&gt;, so be sure to install that plugin first.  Then just drop this code in &lt;code&gt;lib/find_all_in_chunks.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;FindAllInChunks&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_all_in_chunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:per_page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;records&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;next_page&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;FindAllInChunks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and add this line to &lt;code&gt;config/environment.rb&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"find_all_in_chunks"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code is simple.  It just fetches the data in chunks by paginating the results and walking through the pages until it reaches the last one.  Each entry in the page is then &lt;code&gt;yield&lt;/code&gt;ed to the block you pass this finder.  This makes it seem like you are working with a simple &lt;code&gt;each()&lt;/code&gt; iterator, though it will eventually fetch all of the entries.  You can pass &lt;code&gt;will_paginate&lt;/code&gt;'s &lt;code&gt;:per_page&lt;/code&gt; parameter to adjust how many entries are retrieved at one time.&lt;/p&gt;

&lt;h4&gt;3. &lt;code&gt;FasterCSV&lt;/code&gt; as an Import Tool&lt;/h4&gt;

&lt;p&gt;If you need to jump start the database by importing some content, &lt;a href="http://rubyforge.org/projects/fastercsv/"&gt;FasterCSV&lt;/a&gt; can be a big help.  It can easily feed CSV data into an &lt;code&gt;ActiveRecord&lt;/code&gt; subclass using code like:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="no"&gt;FCSV&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;csv_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:headers&lt;/span&gt;           &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="ss"&gt;:header_converters&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:symbol&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="no"&gt;MyARClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordNotSaved&lt;/span&gt; &lt;span class="c1"&gt;# in current Rails&lt;/span&gt;
    &lt;span class="c1"&gt;# handle save failures here…&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This uses the first line of your CSV data as the field names, so be sure they match up to the names in your database.  It's also a good idea to make sure the CSV data is in UTF-8 and set &lt;code&gt;$KCODE = "U"&lt;/code&gt; when using an older version of Rails that doesn't do this for you.&lt;/p&gt;

&lt;p&gt;I tend to just vendor the &lt;code&gt;FasterCSV&lt;/code&gt; source and add a require for it in &lt;code&gt;config/environment.rb&lt;/code&gt;, so I don't have to worry about installing the gem everywhere.&lt;/p&gt;

&lt;h4&gt;4. Learn to Love &lt;code&gt;ActiveRecord&lt;/code&gt;'s &lt;code&gt;:select&lt;/code&gt; Parameter&lt;/h4&gt;

&lt;p&gt;I think the most under used feature of &lt;code&gt;ActiveRecord&lt;/code&gt;'s finders is the &lt;code&gt;:select&lt;/code&gt; parameter.  You really owe it to yourself to play with this sucker until you get the "Ah ha!" moment.&lt;/p&gt;

&lt;p&gt;The concept is simple:  &lt;code&gt;:select&lt;/code&gt; tells &lt;code&gt;ActiveRecord&lt;/code&gt; which columns to fetch from the database.&lt;/p&gt;

&lt;p&gt;By default, everything is fetched, but there are great reasons to exclude some fields.  For example, if you are grabbing a bunch of objects from a sizable table (meaning that it has many fields) but you only need certain fields, throw the rest out!  It will take &lt;code&gt;ActiveRecord&lt;/code&gt; less time to fetch the data and convert it to Ruby and use less memory, possibly making it practical for you to fetch more entries at once.  That's a lot of great gains!&lt;/p&gt;

&lt;p&gt;Another thing to know is that &lt;code&gt;ActiveRecord&lt;/code&gt; takes the field names it uses from the names provided here so use SQL's &lt;code&gt;AS&lt;/code&gt; to get what you want.  You can even add aggregate fields and alias them so they are just like normal fields for this query.&lt;/p&gt;

&lt;p&gt;This has a million different applications, but, to give an example, I pull some email campaign statistics by type using a query like:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="n"&gt;statistics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="ss"&gt;:all&lt;/span&gt;
  &lt;span class="ss"&gt;:select&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"profiles.type, "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
             &lt;span class="s2"&gt;"COUNT(DISTINCT users.id) AS emailed, "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
             &lt;span class="s2"&gt;"COUNT(IF(profiles.viewed_offer = 1, 1, NULL)) AS viewed, "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
             &lt;span class="s2"&gt;"COUNT(IF(profiles.signed_up = 1, 1, NULL)) AS accepted, "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
             &lt;span class="s2"&gt;"COUNT(IF(users.email_status = 'Opted Out', 1, NULL)) AS unsubscribed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:joins&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"INNER JOIN users ON users.id = profiles.user_id "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
             &lt;span class="s2"&gt;"INNER JOIN emailings ON emailings.user_id = users.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:group&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"profiles.type"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this database a &lt;code&gt;User&lt;/code&gt; &lt;code&gt;has_many&lt;/code&gt; &lt;code&gt;Profile&lt;/code&gt;s and &lt;code&gt;Emailing&lt;/code&gt;s are associated with &lt;code&gt;User&lt;/code&gt; objects.  I use &lt;code&gt;:joins&lt;/code&gt; to link all of that together here.  (The &lt;code&gt;:include&lt;/code&gt; option seems to override your custom &lt;code&gt;:select&lt;/code&gt; so I just use &lt;code&gt;:joins&lt;/code&gt; instead.)  Note that I &lt;code&gt;INNER JOIN&lt;/code&gt; these tables to cut down on the data fetched.  It's handy to remember that there are more options to SQL than just what &lt;code&gt;ActiveRecord&lt;/code&gt; uses.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;:select&lt;/code&gt; parameter is the juicy part here.  I setup a group of aggregate fields to track the statistics we care about, aliasing each of these to nice method names for the returned objects.&lt;/p&gt;

&lt;p&gt;This single query combs through a ton of data very quickly and returns all the vital details we care about.  Now it's important to note that what is returned here aren't really &lt;code&gt;Profile&lt;/code&gt; objects as we typically think of them.  These are more summary objects that have a new set of methods we defined in this query (&lt;code&gt;emailed()&lt;/code&gt;, &lt;code&gt;viewed()&lt;/code&gt;, &lt;code&gt;accepted()&lt;/code&gt;, &lt;code&gt;unsubscribed()&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;5. Sneaking in a &lt;code&gt;HAVING&lt;/code&gt; Clause&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;ActiveRecord&lt;/code&gt; doesn't have a parameter for including a &lt;code&gt;HAVING&lt;/code&gt; clause in your database queries and I sometimes find myself needing it.  Luckily, you can sneak it in on the end of your &lt;code&gt;:group&lt;/code&gt; parameter without needing to resort to a &lt;code&gt;find_by_sql()&lt;/code&gt; call.  (I don't recall ever using &lt;code&gt;HAVING&lt;/code&gt; without &lt;code&gt;GROUP BY&lt;/code&gt;, though there probably are some cases where it would make sense to do so.)&lt;/p&gt;

&lt;p&gt;As an example, here's a query from one of my Rails applications that finds all duplicate email addresses in the database:&lt;/p&gt;

&lt;div class="highlight highlight-ruby"&gt;&lt;pre&gt;&lt;span class="n"&gt;duplicates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="ss"&gt;:all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:select&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"email, COUNT(email) AS duplicate_count"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:conditions&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"email IS NOT NULL AND email != ''"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:group&lt;/span&gt;      &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"email HAVING duplicate_count &amp;gt; 1"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</content>
    <author>
      <name>James Edward Gray II</name>
    </author>
  </entry>
</feed>
