4

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?

4

1 回答 1

0

也许我不明白一些事情,但如果你active_by_date改为

  def self.active_by_date
    where("addresses.is_active = ?", true).order('addresses.updated_at DESC')
  end

那么就不能打电话了User.includes(profiles: :addresses).active_by_date吗?

于 2013-06-21T14:44:48.400 回答