Trouble on Eager Loading "Second Degree" Associated Objects

What is the proper way to eager load associated objects for a 'has_many' association?

You should use includes method, like in following:

Article.includes(:comments).where(title: 'Sample text')

For your first case, you don't really need eager loading, since you only select one record, so this is not n+1 problem. You can just do:

article = Article.find(1)
article.comments

If you use include your articles frequently, you may define scope:

scope :with_comments, -> { includes(:comments }

and simply call it:

Article.with_comments.where(title: 'Sample text')

When your relation into which you want to include comments comes from another association, nothing changes, you can do both:

@current_user.articles.includes(:comments)

and

@current_user.articles.with_comments

Trouble on eager loading and using the 'where' method

In case 1 the where clause only applies to categories. If you also want it to apply to comments you can do this:

article_categories =
article
.categories
.includes(:comments)
.where('categories.user_id = ? AND comments.user_id = ?', @current_user.id, @current_user.id)

Eloquent - Having problems using eager loading on nested relationships

You should add foreign key and primary key in relation:

public function universities()
{
return $this->hasMany('\StudentApp\Models\University', 'university_id', 'id');
}

ActiveRecord: Nested association eager loading does not load grandchild object(s)

So, as it turns out from my digging through Rails logic, 'eager loading' does not create a blank object for an association if the id for the row being joined from the table is NULL. Checking for whether the object was created by using .nil? on the association will run a query to look for it, defeating the purpose of eager loading.

Because it's a has_one relationship, checking whether it was loaded doesn't have a fancy function that I can find, like loaded? does for has_many relationships. So what I ended up doing was checking for the existence of annotation_note in the AnnotationGroup object's annotation_cache. Relevant code change below:

'qa_note' => anno_group.association_cache.keys.include?(:annotation_note) ? anno_group.annotation_note.note : nil

Why isn't this second-level eager loading working?

Maybe you should try to call includes on the Model class like:

@subratings = Subrating.includes(thing: [:categories])

as documented in http://apidock.com/rails/ActiveRecord/QueryMethods/includes

although it also should work the way you are trying it, since .all is an alias for .find(:all) but then i would propose to try:

@subratings = Subrating.all( :includes => { :thing => [:categories] })

(note that i changed include to includes and made thing point to an array)

Trouble when filtering eager loaded data

Just to confirm: David Underwood is correct that find_by will make a database call. In fact, find_by is basically just a wrapper for where and take, which will indeed make a DB call.

An alternative way to accomplish what you're looking for is to simply treat the collection proxy as an array, by using the find method, like so:

@articles.each do |article|
logger.debug article.comments.find {|comment| comment.title == "Hello A"}
end

Update:

I have to admit, this one was a bit of a doozy.

The way to accomplish this in the manner you're looking for is to add another has_many relationship that specifically contains the filtering condition you want, like so:

class Article < ActiveRecord::Base

has_many :hello_A_comments, -> { where(title: "Hello A") }, class_name: "Comment"

# rest of class
end

And then, you eager load using this new association, like so:

@articles = @current_user.articles.includes(:hello_A_comments)

This part is very important:
You now access the association not through the original :comments association method, but through the new hello_A_comments method instead, like so:

@articles.first.hello_a_comments

Unfortunately, as you can see, this method is not very dynamic, and sadly I do not know how to allow for variable conditions in the association in the case of eager loading. This answer might be a good resource to look at, but in the case of eager loading, honestly I don't believe its possible. If that is an issue, you might be stuck with the array method I mentioned earlier.



Related Topics



Leave a reply



Submit