Handy scopes for associations
If your Rails project has a has-many association and you want a way of finding records that have no associated records, or, records that have at least one associated record, you might find this post useful.
Suppose you have classes Person
and Friend
that are associated via a has_many
relationship:
class Person < ActiveRecord::Base
has_many :friends
end
class Friend < ActiveRecord::Base
belongs_to :person
end
How do you find persons
that have no friends
?
Person.includes(:friends).where("friends.person_id IS NULL")
Or that have at least one friend
Person.includes(:friends).where("friends.person_id IS NOT NULL")
Using Arel
To accomplish this with Arel
set up the following scopes on Friend
(thanks to @macfanatic for the tip),
class Friend
belongs_to :person
scope :to_somebody, ->{ where arel_table[:person_id].not_eq(nil) }
scope :to_nobody, ->{ where arel_table[:person_id].eq(nil) }
end
And then, Persons who have at least one friend:
Person.includes(:friends).merge(Friend.to_somebody)
The friendless:
Person.includes(:friends).merge(Friend.to_nobody)
Note: If you are on Rails 4 don’t forget to append references(:friends)
to these.