<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>~iany/ Active Record</title><link>https://blog.iany.me/tags/active-record/</link><description>Recent content in Active Record «~iany/»</description><language>en-US</language><managingEditor>me@iany.me (Ian Yang)</managingEditor><webMaster>me@iany.me (Ian Yang)</webMaster><copyright>CC-BY-SA 4.0</copyright><lastBuildDate>Fri, 23 Aug 2013 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iany.me/tags/active-record/index.xml" rel="self" type="application/rss+xml"/><item><title>ActiveRecord includes and preload</title><link>https://blog.iany.me/2013/08/active-record-includes-and-preload/</link><pubDate>Fri, 23 Aug 2013 00:00:00 +0000</pubDate><author>me@iany.me (Ian Yang)</author><guid>https://blog.iany.me/2013/08/active-record-includes-and-preload/</guid><description>&lt;p&gt;&lt;code&gt;ActiveRecord&lt;/code&gt; has two &lt;a href="http://apidock.com/rails/ActiveRecord/QueryMethods"&gt;query methods&lt;/a&gt; to eager load associations, &lt;a href="http://apidock.com/rails/v3.2.13/ActiveRecord/QueryMethods/includes"&gt;includes&lt;/a&gt; and &lt;a href="http://apidock.com/rails/v3.2.13/ActiveRecord/QueryMethods/preload"&gt;preload&lt;/a&gt;. Although the documentation of &lt;code&gt;preload&lt;/code&gt; says&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Allows preloading of args, in the same way that includes does.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Indeed the two methods have some differences.&lt;/p&gt;
&lt;p&gt;In simple words, prefer &lt;code&gt;includes&lt;/code&gt; to eager load associations. Use &lt;code&gt;preload&lt;/code&gt; only when&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you want to customize &lt;code&gt;select&lt;/code&gt; columns, or&lt;/li&gt;
&lt;li&gt;you meet error &amp;ldquo;Can not eagerly load the polymorphic association&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of the two methods eager load associations to avoid N+1 queries. However, &lt;code&gt;includes&lt;/code&gt; is more aggressive. If it detects that the associations tables are already joined, through explicitly &lt;code&gt;joins&lt;/code&gt; or implicit references in &lt;code&gt;where&lt;/code&gt;, it overwrites &lt;code&gt;select&lt;/code&gt; fields from the joined query and construct result set from it, rather than loading associations in a separate query. See the generated SQL statement below and the fields aliases like &lt;code&gt;t0_r0&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;irb(main):049:0&amp;gt; User.includes(:articles).joins(:articles)
SQL (0.7ms) SELECT &amp;quot;users&amp;quot;.&amp;quot;id&amp;quot; AS t0_r0,
&amp;quot;users&amp;quot;.&amp;quot;login&amp;quot; AS t0_r1,
&amp;quot;users&amp;quot;.&amp;quot;name&amp;quot; AS t0_r2,
&amp;quot;users&amp;quot;.&amp;quot;created_at&amp;quot; AS t0_r3,
&amp;quot;users&amp;quot;.&amp;quot;updated_at&amp;quot; AS t0_r4,
&amp;quot;articles&amp;quot;.&amp;quot;id&amp;quot; AS t1_r0,
&amp;quot;articles&amp;quot;.&amp;quot;title&amp;quot; AS t1_r1,
&amp;quot;articles&amp;quot;.&amp;quot;content&amp;quot; AS t1_r2,
&amp;quot;articles&amp;quot;.&amp;quot;user_id&amp;quot; AS t1_r3,
&amp;quot;articles&amp;quot;.&amp;quot;created_at&amp;quot; AS t1_r4,
&amp;quot;articles&amp;quot;.&amp;quot;updated_at&amp;quot; AS t1_r5
FROM &amp;quot;users&amp;quot;
INNER JOIN &amp;quot;articles&amp;quot;
ON &amp;quot;articles&amp;quot;.&amp;quot;user_id&amp;quot; = &amp;quot;users&amp;quot;.&amp;quot;id&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, if the table is not joined yet, &lt;code&gt;includes&lt;/code&gt; will fallback to &lt;code&gt;preload&lt;/code&gt;, which loads association in a separate query. See the SQL in log below that articles are eager loaded in another &lt;code&gt;SELECT&lt;/code&gt; query.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;irb(main):050:0&amp;gt; User.includes(:articles)
User Load (0.1ms) SELECT &amp;quot;users&amp;quot;.* FROM &amp;quot;users&amp;quot;
Article Load (0.2ms) SELECT &amp;quot;articles&amp;quot;.* FROM &amp;quot;articles&amp;quot;
WHERE &amp;quot;articles&amp;quot;.&amp;quot;user_id&amp;quot; IN (1, 2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because &lt;code&gt;includes&lt;/code&gt; may (or may not) overwrite &lt;code&gt;select&lt;/code&gt;, if you have your own &lt;code&gt;select&lt;/code&gt; clause, use &lt;code&gt;preload&lt;/code&gt; instead. See example below:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;users = User.joins(:articles).select(
'users.*, articles.created_at as last_posted_at'
)
users.includes(:articles).first.last_posted_at
# NoMethodError: undefined method `last_posted_at'
users.preload(:articles).first.last_posted_at
# =&amp;gt; &amp;quot;2013-08-23 11:20:36.536968&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Older version of Rails has trouble to &lt;code&gt;includes&lt;/code&gt; polymorphic associations. It seems the newer version of Rails is smart enough to fallback to &lt;code&gt;preload&lt;/code&gt;. However if you still see the error &amp;ldquo;Can not eagerly load the polymorphic association&amp;rdquo;, try switching to &lt;code&gt;preload&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="references"&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://apidock.com/rails/ActiveRecord/QueryMethods"&gt;ActiveRecord QueryMethods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations"&gt;ActiveRecord Eater Loading Associations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><category domain="https://blog.iany.me/post/">Posts</category><category domain="https://blog.iany.me/tags/active-record/">Active Record</category><category domain="https://blog.iany.me/tags/performance/">Performance</category><category domain="https://blog.iany.me/tags/rails/">Rails</category></item><item><title>ActiveRecord uniq, count and distinct</title><link>https://blog.iany.me/2013/07/active-record-uniq-count-and-distinct/</link><pubDate>Tue, 16 Jul 2013 00:00:00 +0000</pubDate><author>me@iany.me (Ian Yang)</author><guid>https://blog.iany.me/2013/07/active-record-uniq-count-and-distinct/</guid><description>&lt;p&gt;&lt;code&gt;ActiveRecord&lt;/code&gt; has two methods to remove duplicates. Method &lt;code&gt;uniq&lt;/code&gt; and option &lt;code&gt;distinct: true&lt;/code&gt; in method &lt;code&gt;count&lt;/code&gt;. I thought &lt;code&gt;uniq.count&lt;/code&gt; and &lt;code&gt;count(distinct: true)&lt;/code&gt; were identical. Indeed, &lt;code&gt;uniq.count&lt;/code&gt; still counts duplicates, and &lt;code&gt;count(distinct: true)&lt;/code&gt; must be used here.&lt;/p&gt;
&lt;p&gt;In simple words, use &lt;code&gt;uniq&lt;/code&gt; to get unique result set, use &lt;code&gt;count(distinct: true)&lt;/code&gt; to count unique result.&lt;/p&gt;
&lt;p&gt;For example, user has many activities, and I want to get all users having a specific type of activities:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ruby"&gt;users = User.joins(:activities).where(
activities: { activity_type: 'purchase'}
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because a user may have multiple activities with the same type, the result above may contain duplicate users. Method &lt;code&gt;uniq&lt;/code&gt; can be used here to remove the duplicates:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;users = users.uniq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But &lt;code&gt;users.uniq.count&lt;/code&gt; generates SQL like below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT DISTINCT COUNT(*) ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This SQL counts all records with duplicates, and apply &lt;code&gt;DISTINCT&lt;/code&gt; on the count, which has only one row. So &lt;code&gt;DISTINCT&lt;/code&gt; has no effect here.&lt;/p&gt;
&lt;p&gt;On the other hand, &lt;code&gt;users.count(distinct: true)&lt;/code&gt; generates SQL below, which removes duplicates first, then count the result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT COUNT(DISTINCT users.id) ...
&lt;/code&gt;&lt;/pre&gt;</description><category domain="https://blog.iany.me/post/">Posts</category><category domain="https://blog.iany.me/tags/active-record/">Active Record</category><category domain="https://blog.iany.me/tags/database/">Database</category><category domain="https://blog.iany.me/tags/rails/">Rails</category></item></channel></rss>