Wednesday, December 12, 2012

One plus N (1+N) Query Problem

Dec 12,2012 See Documentation for Eager Loading solution.

However, there are cases that are hard to Eager Load. One example is:

@leavetype_ids = Leavetype.pluck(:id)

for user in User.all
  for lt in @leavetype_ids
    user.leave_credits.with_lt_id(lt).first_or_initialize
  end
end
scope :with_lt_id, ->(lt) {where(:leavetype_id => lt)}

That's a no-no, a query inside a loop is a heavy procedure. Instead, load them (via includes) and use array methods.

@leavetype_ids = Leavetype.pluck(:id)

for user in User.includes(:leave_credits)
  for lt in @leavetype_ids
    x = first_with_lt_id(lt,user.leave_credits)
    x ||= user.leave_credits.new(:leavetype_id => lt)
  end
end
def first_with_lt_id(lt,coll); coll.select{|c| c.leavetype_id == lt}.first; end

where :select_lt_id is a Array.select method.

EDIT 20121218: Eager loaded the problem but use :select_lt_id still

@users = User.includes({:leave_credits => [:leave_applications, :leavetype]}, :leave_banks, :department)

No comments:

Post a Comment