ruby on rails - How do I eliminate multiple joins of the same table in a has_many through association with multiple scopes? -
given following models , associations:
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' indicate whether position 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 returns correct number of results , generates correct query. however, when attempt employee.title_is(123).is_active (which want return employees title_id 123 , active, results in multiple joins position. no problem except active check applies 1 of position joins thereby resulting in both active positions , inactive positions:
select count(*) `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` positions.active = true) , (titles.id = 123 or titles.name = 123) i should note technically if had way of adding in clause positions_employees_join.active = true, work correctly well, though don't know how in scope.
i skip using titles association in title_is scope.
scope :title_is, ->(name) { joins(:positions => :title).merge(title.is_or_name_is(name)) } keep association because still gives more efficient queries when calling employee_instance.titles rather employee_instance.positions.titles.
but purpose of scope, doing joins(:positions => :title) tells activerecord want use regular join other scopes call joins(:positions).
Comments
Post a Comment