In a rails application I am working on I have the following setup:
class Volunteer < AR::Base
has_many :engagements
end
class Engagement < AR::Base
belongs_to :volunteer
end
I am trying to select all volunteers who are not engaged on a particular date or between date ranges:
scope :not_engaged_on, lambda { |q| joins(:engagements).where(["engagements.date != ?", q])}
scope :not_engaged_between, lambda { |s, e| joins(:engagements).where(["engagements.date NOT BETWEEN ? AND ?", s, e]) }
These scopes I am merging along with other scopes to filter volunteers.
The above scope :not_engaged_between produces the following SQL:
SELECT "volunteers".* FROM "volunteers" INNER JOIN "accounts" ON "accounts"."user_id" = "volunteers"."id" AND "accounts"."user_type" = 'Volunteer' INNER JOIN "engagements" ON "engagements"."volunteer_id" = "volunteers"."id" WHERE (accounts.activation_state = 'active') AND (engagements.date NOT BETWEEN '2012-07-30' AND '2012-08-04')
The problem is a Volunteer might not have any engagements till now and in that case the query totally ignores those volunteers. How can I make return all volunteers even if they don’t have any engagements?
You need a
not existsto do this. This syntax is a bit heavy on SQL, maybe there’s a better arel-way to do it.