Monday, March 10, 2008

RoR: each

So I was needing to do some eager loading in a very particular way. I had an array of users, and I needed to eager load some tables:

users.each { |user| user.reload(:include => :country) }
# use user.country somewhere down below

Reading the API, it says that it will pass on any options passed into reload to the find. I thought, "Great! It'll eager load things". Well, I was wrong. When I got down to using country, it did another SQL find! I thought that maybe the reload doesn't do eager loading, so I tried to force it:

users.each { |user| user = User.find(user.id, :include => :country) }

This should definitely work, except when I accessed my individual users, they were the same as if I hadn't executed the above line. It seems that the assignment to the user object doesn't change the one in the users array! However, you can change the attributes of the user object. My guess is that when assignment is involved, a new user object is created in the scope of the each block.

I ended up doing a very crude, brute force way:

i = 0
users.each do |user|
users[i] = User.find(user.id, :include => :country)
i = i + 1
end

This has solved my problem, albeit ugly.


W

No comments: