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 user_id.

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_add_userid_to_cases.rb where 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 cases called 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

The belongs_to association

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 end:

belongs_to :user

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 user.

The has_many association

Similarly to how each case belongs_to an user, each user has_many cases. To reflect this, in the user model in /app/models/user.rb type before end:

has_many :cases

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.

The current_user object

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 current_user.

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 case.

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.

So in /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:

results matching ""

    No results matching ""