简体   繁体   中英

How to set up a has_many relation in Rails for two different types of relation between two tables?

Here's my schema:

Participant = 
   id: int
   user_id: int
   program_id: int
   ... other fields
end

User = 
   id: int
   name: text
   ... other fields
end

Program = 
   id: int
   user_id:  int # this is the manager of the program
end

So, in English:

  • Users are people.
  • A program is managed by a user.
  • A program also has a set of participants, each of which is a user

And so in Rails:

class Participant
   belongs_to :user
   belongs_to
end

class User
   has_many :programs
   has_many :participants
end

class Program
   has_many :participants
   belongs_to :user
end

Notice that a user really has_many programs, the ones that they manage, as well as has_many programs through participants, which is all the programs that they participate in.

What I want is to be able to say:

  • a_user.manages_programs
  • a_user.participates_in_programs

So two flavors of user has_many programs. I need to do some magic combination of :through, :as, :class, or something along those lines but I can't figure it out so far.

One additional question continuing this example. I now have

class User
  has_many :participations, class_name: "Participant"
  has_many :moderated_programs, class_name: "Program", foreign_key: 'moderator_id'
  has_many :participating_programs, through: :participations, class_name: "Program", source: :program
end

class Participant
  belongs_to :user
  belongs_to :program
end

Notice the third line. What I want is to take advantage of this series of associations: a participant has a user_id and a program_id. I would like to be able to say u1.participating_programs and get a list of one or more programs this user participates in, but the above is not working. Can you tell where I am off base?

I agree with Charles, you have some wording/language issues that are confusing things. Participations may be a better term. I wouldn't recommend polymorphic here - the user may have two different roles, but the users won't be of a different type. Especially if it's possible for a manager to also be a participant...

class User
  has_many :participations
  has_many :programs, through: :participations
  has_many :managed_programs, class_name: 'Program'
end

class Program
  belongs_to :manager, class_name: 'User'
  has_many :participations
  has_many :users, through: :participations
end

# Just a join table.  Nothing special
class Participation
  belongs_to :user
  belongs_to :program
end

First off, just a language thing: I don't think a user has many participants. He is a participant or he is the manager of a program. So he rather has many participations.

You can write this as follows:

class User
    has_many :participations, class_name: "Participant"
    has_many :managed_programs, class_name: "Program"
end

Also, at least in your code above, the Participant class is missing

belongs_to :user

Since it appears that you need to differentiate between two different types of users, the polymorphic functionality would come in handy. Then you don't need an extra participant table. See here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM