Associations Between Models
In a relational database, models are connected to one another.
A Post might have many Comments, an Inventory might have many Items. A Ship might have a Captain.
Relationships in Rails are set in the Model. To connect two things together, we can say:
class Ship < ActiveRecord::Basehas_one :captainend
Likewise we might say:
class Captain < ActiveRecord::Basebelongs_to :shipend
To make this work we need a field in our
The foreign key always goes on the model with the belongs_to relationship.
Many to One Relationships
Say we have a ship that has a lot of cargo. We can express this like so:
class Ship < ActiveRecord::Basehas_many :cargo_itemsend
class CargoItem < ActiveRecord::Basebelongs_to :shipend
We need a ship_id field on the CargoItem model.
Many to Many Relationships
We can also model many to many relationships. Say a ship can belong to more than one fleet, and a fleet can have more than one ship.
class Ship < ActiveRecord::Basehas_and_belongs_to_many :fleetsend
class Fleet < ActiveRecord::Basehas_and_belongs_to_many :shipsend
To make this work, we then need a join table. The join table is named after the two models in alphabetical order, like so:
This table needs two fields:
Presto, they are now connected.
Exercise - Add a one to many relation
Use your scaffolded application that you made in the last section. We are going to add a one to many relation.
Think of a model that makes sense to your domain. If you have shipping, you might make a CrewMember. If you have a Blog, you might choose Comments.
First of all, scaffold the Model model. Refer to the last exercise if you can't remember how to do this.
Comments will need several fields, I'll leave this part up to you, but crucially, comments will need a
blog_post_id: integer field. CrewMembers will need a
ship_id field. Notice how I highlighted that part.
Now set up the relationships
You'll need to extend your models something like the following:
class BlogPosthas_many :commentsendclass Commentbelongs_to :blog_postend
Test the association
Drop into the console and check your association. You should be able to call something like:
post = BlogPost.firstpost.comments
Add validation to your comment. A comment needs a blog_post_id to be valid, plus a couple of other fields. Enforce this.
On your blog_posts/show page, or your ships/show page, list all the join models for a particular blog post. Remember you can use @blog_post.comments to get an array of the comments.
Great. You can now create comments from the comments form, and see them when you view a blog but you will need to manually enter the blog_post_id when creating the comment. Let's fix that.
Optional finishing up
Pick from the following:
- See if you can integrate your comment form right into your blog_post_show page. (tip, in the blog_post_show controller execute:
@comment = Comment.new.
This will let the comment form just work without modifications.)