How to write set-operation queries in ActiveRecord without writing INTERSECT, UNION, or EXCEPT in SQL?

Viewed 724

I have a Rails app for managing volunteers and I'm looking for 'the Rails way' of writing a complex SQL query for filtering all of the volunteer records. I have the following models:

class Volunteer < ActiveRecord::Base
  has_many :volunteer_skills
  has_many :skills, through: :volunteer_skills
  has_many :volunteer_lists
  has_many :lists, through: :volunteer_lists
end

class VolunteerSkill < ActiveRecord::Base
  belongs_to :volunteer
  belongs_to :skill
end

class VolunteerList < ActiveRecord::Base
  belongs_to :volunteer
  belongs_to :list
end

If @lists is an array of List IDs and @skills is an array of Skill IDs

  1. I want to find all volunteers on ANY @lists WITHOUT ANY of @skills.
  2. I want to find all volunteers on ANY @lists WITHOUT ALL of @skills.
  3. I want to find all volunteers on ANY @lists WITH ANY of @skills.
  4. I want to find all volunteers on ANY @lists WITH ALL of @skills.

After seeing this StackOverflow question, I created a solution to this problem using .find_by_sql. When the query involves finding volunteers with ALL @skills, I construct an INTERSECT query. When the query involves finding volunteers with ANY @skills, I construct a UNION query. When the query involves finding volunteers WITHOUT @skills, I format the query with EXCEPT.

Unfortunately, this solution is not NEARLY as friendly as one that makes use of ActiveRecord. I'm pretty new to programming, but the problem I'm trying to solve seems fairly straightforward/common. Is there a better solution that makes use of ActiveRecord?

I'm very grateful for any ideas!

1 Answers
Related