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 post to its creator.

For this, in our Posts 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 Posts table type in terminal:

$ rails generate migration AddUserIdToPosts user_id:integer

Now if you go to /db/migrate you will find a file called 123456_add_userid_to_posts.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:

class AddUserIdToPosts < ActiveRecord::Migration[5.1]
  def change
    add_column :posts, :user_id, :integer
  end
end

What it says is that this migration will add a column to the table posts called user_id of type integer (integer means number).

Now we have to migrate the table. Save the file and type in the console:

$ rails db:migrate

The belongs_to association

Having added in our posts table a user_id field, that tells to which user the post belongs, we need to also reflect this in the posts model. In /app/models/post.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 post belongs to an user.

The has_many association

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

has_many :posts

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

Associating posts to users

Now let's make sure that your app will automatically assign the current's user_id to any newly created posts.

For this we need to edit the create action in the /app/controllers/posts_controller.rb by adding the following two lines of code:

@post.user = current_user
@post.save

Displaying the user’s email

Now that the app knows who is the author of each post, 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/posts/index.html.erb add the list item:

<li>
  <p> <%= "Created by: " + post.user.try(:email).to_s %> </p>
</li>

What we did was add the email of the user who created it.

Now, if you save the file, then go and create a new post, you will see the email of user who created it:

results matching ""

    No results matching ""