鉴于以下模型和协会:
class Employee
has_many :positions
has_many :titles, :through => :positions
scope :is_active, -> { joins(:positions).merge(Position.is_active) }
scope :title_is, ->(name) { joins(:titles).merge(Title.id_or_name_is(name)) }
end
class Position
belongs_to :employee
belongs_to :title
# bool 'active' to indicate whether the position is active or not
scope :is_active, -> { where("active = true") }
end
class Title
has_many :positions
has_many :employees, :through => :positions
scope :id_or_name_is, ->(id_or_name) { where("titles.id = ? OR titles.name = ?", id_or_name, id_or_name) if id_or_name}
end
Employee.is_active
返回正确的结果数并生成正确的查询。但是,当我尝试执行Employee.title_is(123).is_active
时(我想要返回title_id
为123并且处于活动状态的所有员工,它会导致多个连接与位置。这是没有问题的,除了它是活动的check仅适用于其中一个位置连接,从而导致活动位置和非活动位置:
SELECT COUNT(*)
FROM `employees`
INNER JOIN `positions` ON `positions`.`employee_id` = `employees`.`id`
INNER JOIN `positions` `positions_employees_join` ON positions_employees_join`.`employee_id` = `employees`.`id`
INNER JOIN `titles` ON titles`.`id` = `positions_employees_join`.`title_id`
WHERE positions.active = true)
AND (titles.id = 123 OR
titles.name = 123)
我还应该注意,从技术上讲,如果我还有一种方法可以添加where子句positions_employees_join.active = true
,那么它也可以正常工作,虽然我不知道如何在我的范围。
答案 0 :(得分:0)
我会跳过使用titles
范围内的title_is
关联。
scope :title_is, ->(name) { joins(:positions => :title).merge(Title.is_or_name_is(name)) }
保持关联,因为在调用employee_instance.titles
而不是employee_instance.positions.titles
时,它仍然可以为您提供更有效的查询。
但是出于范围的目的,执行joins(:positions => :title)
告诉ActiveRecord您要使用调用joins(:positions)
的其他范围的常规连接。