Writing scopes for many-to-many relationships
-
04-06-2021 - |
Question
I've got an application with 3 models: Renters, Departments, Criteria.
# app/models/department.rb
class Department < ActiveRecord::Base
attr_accessible :name, :abbr
has_many :renter_departments
has_many :renters, :through => :renter_departments
end
and
# app/models/criterium.rb
class Criterium < ActiveRecord::Base
attr_accessible :name
has_many :renter_criteria
has_many :renters, :through => :renter_criteria
end
I'm trying to make two scopes in the Renter model that will let me find renters by department and by criterium.
Here's the code I have:
# app/models/renter.rb
class Renter < ActiveRecord::Base
# Relationships
has_many :renter_departments
has_many :renter_criteria
has_many :departments, :through => :renter_departments
has_many :criteria, :through => :renter_criteria
# Scopes
scope :from_department, lambda { |abbr| joins(:departments).where("abbr = ?", abbr) }
scope :has_criterium, lambda { |criterium| joins(:criteria).where("name = ?", criterium) }
end
Using
Renter.from_department("SCS")
or
Renter.has_criterium("Economic considerations")
works on its own. However, when I try to chain them,
Renter.from_department("SCS").has_criterium("Economic considerations")
I get an error that says:
Renter Load (0.3ms) SELECT "renters".* FROM "renters" INNER JOIN "renter_departments" ON "renter_departments"."renter_id" = "renters"."id" INNER JOIN "departments" ON "departments"."id" = "renter_departments"."department_id" INNER JOIN "renter_criteria" ON "renter_criteria"."renter_id" = "renters"."id" INNER JOIN "criteria" ON "criteria"."id" = "renter_criteria"."criterium_id" WHERE (abbr = 'SCS') AND (name = 'Economic considerations')
SQLite3::SQLException: ambiguous column name: name: SELECT "renters".* FROM "renters" INNER JOIN "renter_departments" ON "renter_departments"."renter_id" = "renters"."id" INNER JOIN "departments" ON "departments"."id" = "renter_departments"."department_id" INNER JOIN "renter_criteria" ON "renter_criteria"."renter_id" = "renters"."id" INNER JOIN "criteria" ON "criteria"."id" = "renter_criteria"."criterium_id" WHERE (abbr = 'SCS') AND (name = 'Economic considerations')
ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: name: SELECT "renters".* FROM "renters" INNER JOIN "renter_departments" ON "renter_departments"."renter_id" = "renters"."id" INNER JOIN "departments" ON "departments"."id" = "renter_departments"."department_id" INNER JOIN "renter_criteria" ON "renter_criteria"."renter_id" = "renters"."id" INNER JOIN "criteria" ON "criteria"."id" = "renter_criteria"."criterium_id" WHERE (abbr = 'SCS') AND (name = 'Economic considerations')
Additionally,
>> Renter.from_department("SCS").class
=> ActiveRecord::Relation
>> Renter.has_criterium("Economic considerations").class
=> ActiveRecord::Relation
Any ideas on what I'm doing wrong?
Solution
You need to reference the table name in your scopes:
scope :from_department, lambda { |abbr| joins(:departments).where("departments.abbr = ?", abbr) }
scope :has_criterium, lambda { |criterium| joins(:criteria).where("criteria.name = ?", criterium) }
OTHER TIPS
There are multiple name
columns among the tables you're joining on. Make the WHERE
clause use renters.name
or departments.name
or whichever table has the appropriate name
column.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow