Rails has_many :through Find by Extra Attributes in Join Model
Solution 1:
How about adding something like this into your User model?
has_many :active_events, :through => :event_users,
:class_name => "Event",
:source => :event,
:conditions => ['event_users.active = ?',true]
After that you should be able to get active events for a user just by calling:
User.first.active_events
Solution 2:
Milan Novota has a good solution – but :conditions
is now deprecated and the :conditions => ['event_users.active = ?',true]
bit just doesn't seem very rails anyways. I prefer something like this:
has_many :event_users
has_many :active_event_users, -> { where active: true }, class_name: 'EventUser'
has_many :active_events, :through => :active_event_users, class_name: 'Event', :source => :event
After that you should still be able to get active events for a user just by calling:
User.first.active_events
Solution 3:
Even though your u.events isn't explicitly calling the user_events table, that table is still included in the SQL implicitly because of the necessary joins. So, you can still use that table in your find conditions:
u.events.find(:all, :conditions => ["user_events.active = ?", true])
Of course, if you plan to be doing this lookup a lot then sure, give it a separate association as Milan Novota suggests, but there's no requirement for you to do it that way
Solution 4:
Well, more responsibility is being put in User
model than actually needed, and there is no good reason to do so.
We can first define the scope in EventUser
model because where it actually belongs, like:
class EventUser < ActiveRecord::Base
belongs_to :event
belongs_to :user
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
end
Now, a user could have both kind of events: active events as well as inactive events, so we can define the relationship in User
model as follows:
class User < ActiveRecord::Base
has_many :active_event_users, -> { active }, class_name: "EventUser"
has_many :inactive_event_users, -> { inactive }, class_name: "EventUser"
has_many :inactive_events, through: :inactive_event_user,
class_name: "Event",
source: :event
has_many :active_events, through: :active_event_users,
class_name: "Event",
source: :event
end
The beauty in this technique is that the functionality of being an active or an inactive event belongs to EventUser
model, and if in future the functionality needs to be modified, it would be modified only in one place: EventUser
model, and the changes will be reflected in all other models.