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: