Dudo
Dudo

Reputation: 4169

multiple has_many / belongs_to between the same 2 models

I'm curious how this works... I have several has_many relationships between the same two models. This is for a calendaring app, so a User can be invited to an Event, a User can attend an Event, and an Event belongs to a User for purposes of seeing who created the event.

user.rb

class User < ActiveRecord::Base
  has_many :invites, dependent: :destroy
  has_many :events, through: :invites

  has_many :events

  has_many :attendances, -> { where cancel: false },
                         dependent: :destroy                     
  has_many :events, -> { where "attendances.cancel" => false },
                    through: :attendances

event.rb

class Event < ActiveRecord::Base
  has_many :invites, dependent: :destroy
  has_many :users, through: :invites

  belongs_to :user

  has_many :attendances, -> { where cancel: false },
                         dependent: :destroy              
  has_many :users, -> { where "attendances.cancel" => false },
                   through: :attendances

I also have the corresponding join tables, controlled in their respective models, attendance.rb, and invite.rb.

So... this works as expected. A User has Events when they're attending the Event. I did some tweaking, and realized it was the last thing in the list that was checked. So, if I move the invites to the bottom, then that's what's checked when I do something like User.find(1).events.

Is there a better way to go about this? I feel like this is just asking for trouble, no?

Upvotes: 4

Views: 2200

Answers (1)

CDub
CDub

Reputation: 13344

When I've done this before, I've just changed the name of the relationship to something more unique, then told the has_many what class to look at via class_name. You'll likely have to add the foreign_key parameter on these changed relationships as well, so the SQL knows which key to match against.

Here's the basic idea:

user.rb

class User < ActiveRecord::Base
  has_many :invites, dependent: :destroy
  has_many :invited_events, through: :invites, source: "Event"

  has_many :events # these are events "owned" by the user

  has_many :attendances, -> { where cancel: false }, dependent: :destroy
  has_many :attended_events, -> { where "attendances.cancel" => false }, through: :attendances, source: "Event"
end

event.rb

class Event < ActiveRecord::Base
  has_many :invites, dependent: :destroy
  has_many :invitees, through: :invites, source: "User"

  belongs_to :user # this is the owner of the event

  has_many :attendances, -> { where cancel: false }, dependent: :destroy
  has_many :attendees, -> { where "attendances.cancel" => false }, through: :attendances, source: "User"
end

Upvotes: 2

Related Questions