Reputation: 4997
I have a simple many-to-many
relation between two models and a join table. In my Rails controller, I have an ActiveRecord::Relation object called job_descriptions
which is initialized as JobDescription.all
and then passed through flow controls to apply additional where
statements. Here are my models:
class JobDescription < ActiveRecord::Base
has_many :job_description_experience_levels
has_many :experience_levels, through: :job_description_experience_levels
end
class JobDescriptionExperienceLevel < ActiveRecord::Base
belongs_to :job_description
belongs_to :experience_level
end
class ExperienceLevel < ActiveRecord::Base
has_many :job_description_experience_levels
has_many :job_descriptions, through: :job_description_experience_levels
end
I'm trying to write a query for job_descriptions
to select only those instances that do not have an experience_level
association. How can I do this?
I've tried variations of ob_descriptions.includes(:job_descriptions).where(job_description_experience_levels: {job_description_id: nil})
and job_descriptions.where('id NOT IN (SELECT DISTINCT(job_description_id) FROM job_description_experience_levels)')
but without success.
Most of the resoures I've been able to find on this subject work by calling a query on the model itself (e.g. JobDescription.where(something)
) rather than on an existing relation object.
Thanks!
Edit #1
I managed to solve this on my own before madyrockss answer, but I think that answer is more semantic than my solution. Here is my solution anyways in case it helps someone down the line.
job_descriptions_with_experience_levels = job_descriptions.joins(:experience_levels)
job_descriptions = job_descriptions - job_descriptions_with_experience_levels
It works by finding all the job_descriptions
with experience_levels
and then subtracting that relation from job_descriptions
to get the ones without any experience_levels
.
Upvotes: 0
Views: 546
Reputation: 1875
If job_description
do not have any experience_level
there will be no entry present for that job_description
in job_description_experience_levels
table.
So you can do something like following :
job_desc_ids_with_exp_level = JobDescriptionExperienceLevel.pluck(:job_description_id).uniq
job_descriptions = job_descriptions.where.not(id: job_desc_ids_with_exp_level)
Upvotes: 1