I'm quite new to Rails and I've got a project to do that requires some
many-to-many relations right at the beginning. I'll describe what I
want to do, maybe you could tell me how to realize that.
I have the tables »people« and »courses«. One course can have multiple
people (I'm talking of teachers here) and one person can be in
multiple courses. As I started creating my application in the RESTful
way and I learned that the »has_and_belongs_to_many« association
doesn't work very well with the REST-approach, I created a third table
and model called »teachers« that is the join model between those two,
so the models look like this:
class Course < ActiveRecord::Base
has_many :people, :through => :teachers
class Person < ActiveRecord::Base
has_many :courses, :through => :teachers
class Teacher < ActiveRecord::Base
Now following the RESTful way I should add teachers only through my
»TeachersController«, right? Now what I'd like to do is the following.
When you are creating a new course, then on the same page with the
course form (so /courses/new ) there should be the possibility to add
people as teachers to the course. Then if you edit this course
afterwords it should show you the teachers of this course and make it
possible to get them out of this course and add new ones to the
course. But how can I have that on the same page as the courses? How
do I create a new teacher on the same page where the new or edit form
of a specific course is?
I have really no clue. I mean I don't insist on having the »Add
Teacher« thing on the new course page, but what I don't want, is to
put it on an own page only for adding a teacher.
Would be very happy about some answers.
It is very simple: REST is simply a guide to a good way to structure your program (especially useful for machine to machine communication)… I would suggest you go ahead and create the TeachersController and allow teachers to be added/edited/etc from that controller, because at some point you may want the ability to modify the Teachers stuff directly: if you add any extra properties to the Teachers association beyond just being a cross reference for the course - person relationship.
However, I agree that adding a teacher spot to your course controller seems like a reasonable idea, and it is very easy… although, you should realize, what you really want to do is add a Person to your Course, which you’re doing through your Teacher association. So what you might do is add a couple of text fields to your form where you could enter a Person’s name, then do something like this in the action you are submitting to:
c = Course.create(params[:course])
c.people << Person.find_by_name(params[:teacher_name])
This will automatically create the Teacher association for you.
Your model has not captured the concepts in the domain properly.
Student can have many teachers. Teacher can have many students.
Each link that connects the Student to Teacher is through a Course.
Course breaks up the many to many relationship.
You will know that your design is right when you have two entities
connected by an association descriptive table. For instance, you will
for the entities People and Magazine, InsurancePolicy for People and
Marriage for Man and Woman and so on. This is due to the fact that we
promoting an association class to a regular class. An association
the relationship between two entities. It holds information that does
not belong to
either of the entity that it connects. So InsurancePolicy will have
renewal date and
this date does not logically belong to Person or Insurance. The data
comes alive only
when the connection between the entitities is established.
Remember that habm relationship is sufficient if your domain requires
only a simple
join table. You have to pick the right solution for the problem. If
you need to capture more
than just the foreign keys in the join table then you need to
use :through style declaration.
Yes, there is almost one-to-one correspondence between your model
classes and controllers.
Now you got a better idea of how to design your object model, you can
go back and think
about to represent them in your views.