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