Rails: How to eager load associations with :select (only load select columns from each table)

Posted by kevin Fri, 13 Apr 2007 20:51:06 GMT

I've been avoiding blogging about things that were overly technical for awhile, but screw it, I need more things to write about anyways, so I'll start sharing nuggets of knowledge here as well.

Rails eager loading lets you load sub-elements on the database level, which can be a huge speed increase, though sometimes at a database cost. In my experience, the biggest problem is that items I'm joining together often have a big 'description' column, that can cause memory issues if loaded too indescriminatingly.

@logs = ItemLog.find(:all, :conditions => "target_id=#{@user.id}", :order => 'item_logs.created_at DESC', :limit => 40, :include => 'item')

What I wanted to do was add :select => 'only_rows_i_want'. But rails doesn't let you use :select with :include.

So what I did was do it without the :select, and take a look at the log file to see what the generated query would be. Then I removed the items I wanted and used it as a find_by_sql query:

rows = ItemLog.find_by_sql("SELECT item_logs.`id` AS t0_r0, item_logs.`user_id` AS t0_r1, item_logs.`item_id` AS t0_r2, item_logs.`created_at` AS t0_r3, item_logs.`referer` AS t0_r4, item_logs.`target_id` AS t0_r5, items.`id` AS t1_r0, items.`user_id` AS t1_r1, items.`title` AS t1_r4 FROM item_logs LEFT OUTER JOIN items ON items.id = item_logs.item_id WHERE (target_id=#{@user.id}) ORDER BY item_logs.created_at DESC LIMIT 50")

Then how do you get it to make the sub-elements into the actual objects?

join_dep = ActiveRecord::Associations::ClassMethods::JoinDependency.new(ItemLog, ['item'], nil)
@logs = join_dep.instantiate(rows)

I've put the name of the class I'm doing the find on as the first parameter, the include field I used as the 2nd. It works great with rails 1.2!

Technorati Tags: , ,

Posted in  | 4 comments

Comments

  1. Tim said 34 days later:
    really works! Thanks for explanations :)
  2. Michael K. said 81 days later:
    you know, your head works in the right way... my worked in the opposite way... I'll take your idea ;)
  3. Kevin said 90 days later:
    Really works great with rails 1.2 (thanks for this comment). Wish you good luck in your future projects!
  4. Avi said 157 days later:
    Dude, sickness.

(leave url/email »)