10: Associating users and content
What’s an association
As in real life, things are very often associated. A person has a pet, a pet has an owner. A book may receive many reviews, that can be associated with only one book.
Adding a migration
To have finer control over the content in our system, we would like to associate each case to its creator.
For this, in our
Cases table we need the additional column called
As you probably remember, in order to make structural changes in a table we need a migration. To generate a migration that will add the
user_id column to our
Cases table type in terminal:
$ rails generate migration AddUserIdToCases user_id:integer
Now if you go to
/db/migrate/ you will find a file called
123456 will be a random number. Open this file in Sublime Text. It should define an action called
change that will contain the code:
add_column :cases, :user_id, :integer
What it says is that this migration will add a column to the table
user_id of type
integer (integer means number).
Now we have to make Ruby migrate the table. Save the file and type in the console:
$ rake db:migrate
Having added in our
cases table a
user_id field, that tells to which user the case belongs, we need to also reflect this in the
case model. In
/app/models/case.rb type before
Save the file. As you remember a model describes the structure of the rows in a table. The line above specifies that each row in the table
cases belongs to an
Similarly to how each
cases. To reflect this, in the user model in
/app/models/user.rb type before
You might have observed that the user model already had some parameters added to it by Devise.
In practice the same model can have various characteristics. A model could simultaneously belong to something and also have many other things. For example a model explaining a house belongs_to street and house has_many rooms. On facebook, a status belongs_to user and status has_many comments.
The feature of cases belonging to a user and having many updates will be implemented on the second day of the course.
Using the console to associate records
Since we didn't have a user association when the cases were created, the already existing cases do not belong to a user. To correct this in the rails console type:
> u = User.last > Case.all.each do |c| > c.user = u > c.save > end
This way, we have gone through each case, set its user to the last user in the database and saved it.
When your app will have many users, the current user logged into our system will not be the user that was last signed up, and thus added to the users table. To find who the current user is, Devise has a handy variable called
Associating posts to users
Now that we've manually assigned all the past cases to you, their quickly learning creator, let's make sure that your app will automatically assign the current's
user_id to any newly created
For this we need to edit the
create action in the
/app/controllers/cases_controller.rb by adding the following two lines of code:
@case.user = current_user @case.save
Displaying the user’s email
Now that the app knows who is the author of each case, we would like to display this information to our users.
As you remember, to display anything we need to show it in a view.
/app/views/cases/index.html.erb edit the list item to:
<li> <p> <%= "Case id: " + c.id.to_s %> </p> <p> <%= "Created by: " + c.user.email %> </p> <p> <%= image_tag(c.image_link ) %> </p> </li>
What we did was add the case id and the email of the user who created it. The
<p> </p> tags are HTML paragraphs, we added them to have a little more white space around the content. We will remove them when we will get to restyling.
Now, if you save the file, then go to the
localhost:3000/cases page, you will see more information on each case: