Eager loading with scope in Rails
A solution is to use merge
with eager_load
:
@programs.eager_load(:videos).merge(Video.trailer).map { |p| p.videos.size }
It produces only one query.
As I said, IMO your approach of adding the has_many :trailer_videos, -> { where(video_type: 0) }, class: 'Video'
is the simple and best way to counter your problem. I don't see any drawback in adding more such associations to the model.
In Rails Associations
have an optional scope parameter that accepts a lambda that is applied to the Relation
(see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many-label-Scopes)
So you could write your models as:
# app/models/video.rb
class Video < ActiveRecord::Base
belongs_to :program
scope :trailer, -> { where(video_type: 0) }
...
end
# app/models/program.rb
class Program < ActiveRecord::Base
has_many :videos
has_many :trailer_videos, -> { trailer }, class: 'Video'
...
end
This way you could keep the definition of the scope in Video
and reuse it from Program
.