We’re now officially in the second half of the web dev semester of Starter School. According to Jeff, we’re almost done learning the basics that we need to build out a working prototype of our apps.
Intro to model associations
To really make an app that has a meaningful experience, a developer has to be able to connect virtual objects together. What good is having a user if that user can’t be associated to comments or likes or a movie object without reviews or ratings? In order to relate different models, you have to create a foreign key. A foreign key is a field in one table of a database that uniquely identifies another table in the same database. It essentially establishes a link between the data in two tables. This is not a concept unique to Rails, in fact, it can be used in any relational database.
Associating models is really easy in Rails. For example, if you wanted to add reviews to a
Movie model, you would create a migration to add a foreign key to the
Review model. To do this you would run
rails g migration AddMovieIdToReviews movie_id:integer. When that’s done, you should see a migration in
/db/migrate that looks like this:
```ruby [timestamp]add_movie_id_to_reviews.rb class AddMovieIdToReviews < ActiveRecord::Migration def change add_column :reviews, :movie_id, :integer end end
<!-- more --> This allows you to call something like this in your movies controller: ```ruby movies_controller.rb class MoviesController < ApplicationController def show @movie = Movie.find_by_id(params[:id]) @reviews = Review.where(movie_id: params[:id]) end end
Now that there is a link between the data in the two tables, you can now do more interesting things with your application.
Many to many associations
When sketching out an application’s domain model, there is more to associations than simply relating something like reviews to one movie at a time. What if you wanted to display the cast on any specific movie page, and display the different movies an actor has been in on his or her page? You would have to associate them somehow, but not directly to each other. This is because two tables can’t be children of each other - there would be no place to put the foreign keys. To bypass this, you need to create a join table. A join table is a table in the database that holds foreign key attributes for both sides of the association. For example, movies could be associated with actors through a join table called roles. Each
Role object would have to have a
movie_id and an
actor_id in order to refer to unique
Actor objects. Now, both
Actor need a
role_id to complete the association. So if you wanted to display the cast on a movie’s page, you could add something like this to your movies controller:
```ruby movies_controller.rb class MoviesController < ApplicationController def show @movie = Movie.find_by_id(params[:id]) @roles = Roles.where(movie_id: params[:id]) end end
And this in your view: ```erb show.html.erb <% @roles.each do |role| %> <% actor = Actor.find_by_id(role.actor_id) %> <%= link_to actor.name, actor_path(actor.id) %></p> <% end %>
Although this works, I should note that the logic of finding an actor should not be in the view, but in the model. I’ll probably write a post about abstracting logic to models in another post.