Breaking it down to a minimal example:
class User < ActiveRecord::Base
has_many :profiles
has_many :addresses, through: :profiles
end
class Profile < ActiveRecord::Base
belongs_to :user
has_many :addresses
end
class Address < ActiveRecord::Base
belongs_to :profile
def self.active_by_date
where(is_active: true).order('updated_at DESC')
end
end
class UsersController < ApplicationController
def index
@users = User.includes(profiles: :addresses)
end
end
Suppose that in the above controller action, I want to eager-load the active addresses, sorted by date, for each user's profiles. I could do this:
class User < ActiveRecord::Base
has_many :profiles
has_many :addresses, through: :profiles
has_many :active_addresses_by_date, through: :profiles,
source: :addresses, class_name: Address,
conditions: ['address.is_active = ?', true],
order: 'address.updated_at DESC'
end
class UsersController < ApplicationController
def index
@users = User.includes(profiles: :active_addresses_by_date)
end
end
But since I can't reuse the active_by_date
scope on Address
, the condition and order now exist in two places. I'd like to DRY this up so that, as in the first version, the concept of "active addresses by date" exists only in the Address
model. Ideally, in the view I would be able to call @users.each { |user| user.addresses.active_by_date }
without firing any queries. Is this possible under ActiveRecord, and if so, how would I go about it?