Hello 👋 Welcome to my corner of the internet. I write here about the different challenges I encounter, and the projects I work on. Find out more about me.
To retrieve a collection of related models through a has_many :through
relation, with a different name (:source
) and one or many conditions, use the following:
class Event < ActiveRecord::Base
has_many :invitees,
->{ where "invites.accepted = false" },
through: :invites,
source: :user
has_many :participants,
->{ where "invites.accepted = true" },
through: :invites,
source: :user
end
Now when you do Event.first.invitees
or Event.first.participants
, you’ll get the right Activerecord CollectionProxy as usual.
This assumes there are the additional models Invite
(with an attribute accepted
) and User
.
The lambda allows you to place the condition, the through
allows you to grab the associated records and the source
allows you to name which type of model is to be associated. Because I’m renaming the set of users as ‘invitees’ or ‘participants’, that’s necessary.
I found out that the order of the lambda -> through -> source is essential to make this work, so make sure you get that right.
Retrieving records this way keeps my controller code cleaner by not having to do conditions on the retrieved collection. Also, knowing you can filter associated records through conditions ‘in’ the model, has prevented me from making an overcomplicated database design.