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
Copy One Slide from Google Slides into a New Presentation Using API
Brew Install Coreutils Failing 10.9.5 Osx
Loop Within Loop in Rails Controller
-Bash: /Usr/Local/Bin/Heroku: /Usr/Local/Bin/Ruby: Bad Interpreter: No Such File or Directory
Ruby Getting Deeply Nested JSON API Data
Rvm and Gems, Bundle Show and Gem List
Why Does Ruby '**' Operator Have Higher Precedence Than Unary '-'
Fresh Rails App Defaulting to Postgres Instead of SQLite3
Regex to Match Mm/Dd/Yyyy Hh:Mm:Ss Am or Pm
How to Create an Association Between Two Rails Models
Ruby Daemon Process to Keep Objects Alive for Transient Ruby Instances
Deep Convert Openstruct to JSON
How to Reduce the Quality of an Uploading Image Using Paperclip