2014-12-05 32 views
0

鑑於以下型號和協會:如何通過關聯多個作用域來消除has_many中同一個表的多個連接?

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並且處於活動狀態的所有員工時,它會導致帶有位置的多個連接,除非該活動檢查僅適用於某個職位加入從而導致主動位置和非活動位置:

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

我會跳過使用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)

+1

哎呦。我的錯。我沒有仔細觀察你在'Position'模型中的關聯。 我已更新答案以反映您的意見。謝謝 :) – 2014-12-05 23:50:23

相關問題