3

I've googled, read the docs, and watched railscast, but I can't wrap my head around this. Please help. I'm running the latest stable Rails and Ruby 1.9.3, on Ubuntu 13.04.

I have a User model, and an Event model. Right now, there is a has_and_belongs_to_many relationship between the two.

In real life, however, a User relates to the Event as either a Lecturer or a Student. A User can be both a Student and Lecturer, but not for the same event. Lecturer or Student are not yet models in my app, and I'm unsure if they should be separate models. I need help with implementing this logic.

What I want to achieve is something like this:

Event.first.lecturers # Should return Users that are Lecturers for this particular Event.

Event.first.students # Should return Users that are Students for this particular Event

User.first.events :as => :student # Should return Events for a particular User where the User is a Student

User.first.events :as => :lecturer # Should return Events for a particular User where the User is a Lecturer

I'm thinking perhaps a has_many :through association might work, but I'm so confused. Any and all guidance appreciated.

Regards,

Nadeem

Nadeem J.Q.
  • 163
  • 1
  • 2
  • 7

1 Answers1

4

You can create two join tables events_students and events_lecturers and setup models like this

class Event < ActiveRecord::Base
  has_and_belongs_to_many :students, :class_name => 'User', :join_table => :events_students, :association_foreign_key => :user_id
  has_and_belongs_to_many :lecturers, :class_name => 'User', :join_table => :events_lecturers, :association_foreign_key => :user_id
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :student_events, :class_name => 'Event', :join_table => :events_students, :association_foreign_key => :event_id
  has_and_belongs_to_many :lecturer_events, :class_name => 'Event', :join_table => :events_lecturers, :association_foreign_key => :event_id
end

And then access it:

Event.first.students
Event.first.teachers
User.first.student_events
User.first.lecturer_events

UPD.

Another solution is to use has_many :through

class User < ActiveRecord::Base 
  has_many :event_assignments
  has_many :student_events, :through => :event_assignments, :source => :event, :conditions => {'event_assignments.type' => 'EventAssignment::Student'}
  has_many :lecturer_events, :through => :event_assignments, :source => :event, :conditions => {'event_assignments.type' => 'EventAssignment::Lecturer'}
end

class Event < ActiveRecord::Base 
  has_many :event_assignments
  has_many :students, :through => :event_assignments, :source => :user, :conditions => {'event_assignments.type' => 'EventAssignment::Student'}
  has_many :lecturers, :through => :event_assignments, :source => :user, :conditions => {'event_assignments.type' => 'EventAssignment::Lecturer'}
end

class EventAssignment < ActiveRecord::Base 
  belongs_to :user
  belongs_to :event
end

class EventAssignment::Student < EventAssignment
end

class EventAssignment::Lecturer < EventAssignment
end

I'm using STI for EventAssignment model because it can be useful if you have different logic for different type of assignments. But if don't need it, just use another column name instead of type in join model to identify relation type:

class User < ActiveRecord::Base 
  has_many :event_assignments
  has_many :student_events, :through => :event_assignments, :source => :event, :conditions => {'event_assignments.kind' => 'student'}
  has_many :lecturer_events, :through => :event_assignments, :source => :event, :conditions => {'event_assignments.kind' => 'lecturer'}
end

class Event < ActiveRecord::Base 
  has_many :event_assignments
  has_many :students, :through => :event_assignments, :source => :user, :conditions => {'event_assignments.kind' => 'student'}
  has_many :lecturers, :through => :event_assignments, :source => :user, :conditions => {'event_assignments.kind' => 'lecturer'}
end

class EventAssignment < ActiveRecord::Base 
  belongs_to :user
  belongs_to :event
end
Babur Ussenakunov
  • 1,995
  • 2
  • 16
  • 16
  • Apologies, I was not notified of your answer. And, thanks! I tried your first solution. But, both Event.lecturers and Event.students return the same results. I'm saving lecturers like this: event_in_db.lecturers << user Also, in the join tables events_students and events_lecturers, I tried both user_id and student_id/lecture_id as column. Didn't seem to matter. – Nadeem J.Q. Dec 25 '13 at 22:50
  • Seems like that first solution didn't work because I forgot to add `join_table` option to `Event` model – Babur Ussenakunov Dec 26 '13 at 13:07