It eager-loaded the AR::Relation when calling `==` method
Closed this issue · 5 comments
I recently had trouble with unexpected eager-loading. I have something like this:
class Post < ActiveRecord::Base
belongs_to :user
scope :rank, -> {
# do some ranking..
}
end
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
end
def filter_scope(scope)
scope = scope.rank if scope == Post || (scope.is_a?(ActiveRecord::Relation) && scope.klass == Post)
# ...
scope
end
filter_scope(user.posts)
The expected result of filter_scope
is an ActiveRecord::Relation
object and it should not execute any queries. However, it triggered the query at the line scope = scope.rank if scope == Post
:
SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (?)
If I change the variables position, the problem goes away:
scope = scope.rank if Post == scope #...
# Or also work with this:
scope = scope.rank if scope.equal?(Post) # ...
And if I disable Goldiloader, the problem also does not happen.
FYI, I'm using Rails 4.2.4.
Thanks for filing the issue. I'll take a look.
Sorry @jturkel the real code actually uses an AR association filter_scope(user.posts)
. I updated the description. You might be able to reproduce the problem now.
I double-checked the problem, looks like it's a nature of Rails when we perform ==
on an ActiveRecord::Associations::CollectionProxy
within any kinds of objects, it will try to load the collection firstly, then compares these objects.
user.posts == nil # => Load user's posts
nil == user.posts # => Won't load user's posts.
Interestingly that it does not happen with an ActiveRecord::Relation
:
Post.where(user_id: user.id) == nil # => Won't load the posts
So, this does not belong to Goldiloader. I'm sorry for my mistake, thank you for your time @jturkel. We should close this issue :)
No worries. Glad it didn't turn out to be a Goldiloader issue :)