Multiple relationships between models

Hi,
I’m fairly new to RoR and I’m trying to figure out the best way to deal
with Users in my application. I’ve got (for the purpose of this thread)
3 models, User, Subject, and SubjectUserAssignment.

The user model is joined to the Subject model with the following,
creating a many to many relationship between User and Subject:

has_many :subjects, :through => :subject_user_assignments
has_many :subject_user_assignments

Likewise, the Subject model:

has_many :users, :through => :subject_user_assignments
has_many :subject_user_assignments
belongs_to :user, :foreign_key => “user_id_created”
belongs_to :user, :foreign_key => “user_id_updated”

This works fine, I can return all users for a given subject, and all
subjects for a given user. The problem is that the Subject model has
user_id_created and user_id_updated fields, which contain the user_id of
the user(s) who created and updated the subject. So a user can either be
related to a subject because they’re assigned to it, or because they
created/updated it, or both. How do I go about specifying this in my
User model? User.subjects should return all subjects assigned to a user,
but I need something else like User.created_subjects to show all
subjects created by a user. Am I using :foreign_key correctly in the
Subject model?

Al Rowan wrote in post #960389:

Hi,
I’m fairly new to RoR and I’m trying to figure out the best way to deal
with Users in my application. I’ve got (for the purpose of this thread)
3 models, User, Subject, and SubjectUserAssignment.

The user model is joined to the Subject model with the following,
creating a many to many relationship between User and Subject:

has_many :subjects, :through => :subject_user_assignments
has_many :subject_user_assignments

I would urge you to find a more descriptive name than
SubjectUserAssignment. Perhaps Assignment or even Interest might be
better.

Likewise, the Subject model:

has_many :users, :through => :subject_user_assignments
has_many :subject_user_assignments
belongs_to :user, :foreign_key => “user_id_created”
belongs_to :user, :foreign_key => “user_id_updated”

This works fine, I can return all users for a given subject, and all
subjects for a given user. The problem is that the Subject model has
user_id_created and user_id_updated fields, which contain the user_id of
the user(s) who created and updated the subject. So a user can either be
related to a subject because they’re assigned to it, or because they
created/updated it, or both. How do I go about specifying this in my
User model? User.subjects should return all subjects assigned to a user,
but I need something else like User.created_subjects to show all
subjects created by a user. Am I using :foreign_key correctly in the
Subject model?

You’re using :foreign_key correctly, but you’re not using belongs_to
correctly. Remember that the first argument to belongs_to is the name
of the association, not necessarily the class or table. So right now,
you’re creating two different associations called user (presumably one
is overwriting the other). What you want is something like
belongs_to :creator, :foreign_key => ‘user_id_created’, :class_name =>
‘User’
belongs_to :updater, :foreign_key => ‘user_id_updated’, :class_name =>
‘User’

Please refer to the belongs_to rdoc for more info on how this all works.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Al Rowan wrote in post #960389:

Hi,
I’m fairly new to RoR and I’m trying to figure out the best way to deal
with Users in my application. I’ve got (for the purpose of this thread)
3 models, User, Subject, and SubjectUserAssignment.

The user model is joined to the Subject model with the following,
creating a many to many relationship between User and Subject:

has_many :subjects, :through => :subject_user_assignments
has_many :subject_user_assignments

Likewise, the Subject model:

has_many :users, :through => :subject_user_assignments
has_many :subject_user_assignments
belongs_to :user, :foreign_key => “user_id_created”
belongs_to :user, :foreign_key => “user_id_updated”

This works fine, I can return all users for a given subject, and all
subjects for a given user. The problem is that the Subject model has
user_id_created and user_id_updated fields, which contain the user_id of
the user(s) who created and updated the subject. So a user can either be
related to a subject because they’re assigned to it, or because they
created/updated it, or both. How do I go about specifying this in my
User model? User.subjects should return all subjects assigned to a user,
but I need something else like User.created_subjects to show all
subjects created by a user. Am I using :foreign_key correctly in the
Subject model?

First, unless you fear naming conflicts I think and Assignment model
would stand on it’s own so I’ll present my suggestion based on that.

User

has_many :assignments
has_many :subjects, :through => :assignments

Assignment

belongs_to :user
belongs_to :subject

Subject

has_many :assignments
has_many :users, :through => :assignments

This takes care of the many-to-many association:
user.assignments
user.subjects
subject.assignments
subject.users

Now you have two additional one-to-many associations between User and
Subject. A Subject has only one creator and one last_updater. So add two
foreign keys created_by_id and last_updated_by_id to the Subject model
and define the associations:

User

has_many :assignments
has_many :subjects, :through => :assignments
has_many :created_subjects, :class => “Subject”, :foreign_key =>
:created_by_id
has_many :last_updated_subjects, :class => “Subject”, :foreign_key =>
:last_updated_by_id

Subject

has_many :assignments
has_many :users, :through => :assignments
belongs_to :creator, :class => “User”, :foreign_key => :created_by_id
belongs_to :last_updater, :class => “User”, :foreign_key =>
:last_updated_by_id

Which adds:
user.created_subjects
user.last_updated_subjects

subject.creator
subject.last_updater

Robert W. wrote in post #960397:

has_many :last_updated_subjects, :class => “Subject”, :foreign_key =>
:last_updated_by_id

Correction:
Should have been :class_name not :class

has_many :last_updated_subjects, :class_name => “Subject”, :foreign_key
=> :last_updated_by_id