user_idを用いて
投稿とユーザーを紐付ける
各投稿に「どのユーザーがその投稿を作成したか」という情報を
持たせるために、postsテーブルにuser_idというカラムを用意します。
以下の図では、投稿のuser_idが1となっているため、
投稿を作成したのはidが1のユーザーであることがわかります。
postsテーブルにuser_idカラムを追加する
カラムrails g migrationrails db:migrateadd_column
まずは左の図のように「rails g migration」を用いて、add_user_id_to_postsというファイル名のマイグレーションファイルを作成します。
マイグレーションファイルの中身は、右の図のように変更し、
「rails db:migrate」を実行しましょう。
user_idのバリデーション
validatespresence
postsテーブルにuser_idカラムが追加できていることを
確認できたら、user_idにバリデーションを設定しましょう。
誰が投稿したか、という情報は必ずあるべきなので、
user_idに「presence: true」を指定します。
投稿したユーザーのidを保存しよう
newメソッド
新規投稿作成時に、user_idの値をいれて保存するようにしましょう。
投稿したユーザーは、現在ログインしているユーザーですので、「@current_user.id」で取得することができます。
以下の図のように、newメソッドの部分で、user_idの値として「@current_user.id」いれましょう。
def create
@post = Post.new(
content: params[:content],
# user_idの値をログインしているユーザーのidにしてください
user_id: @current_user.id
)
if @post.save
flash[:notice] = “投稿を作成しました”
redirect_to(“/posts/index”)
else
render(“posts/new”)
end
end
user_idから
ユーザー情報を取得しよう
find_by
ユーザー名やユーザー画像を表示するためには、
user_idカラムの値から、そのユーザーの情報を取得する必要があります。
今回は投稿詳細ページなので、postsコントローラのshowアクション内で、
「@post.user_id」を用いて、そのidに該当するユーザーの情報を
データベースから取得しましょう。
posts_controller.rb
def show
@post = Post.find_by(id: params[:id])
# 変数@userを定義してください
@user = User.find_by(id: @post.user_id)
end
show.html.erb
“>
<%= link_to(@user.name, "/users/#{@user.id}") %>
モデルにインスタンスメソッドを定義する
インスタンスメソッド
Railsではモデル内にインスタンスメソッドを定義することができます。
左の図のようにPostモデル内で定義したインスタンスメソッドは、右の図のようにpostインスタンスに対して用いることができます。
インスタンスメソッドについて忘れてしまった人は、Ruby 学習コースⅣ を復習しておきましょう。
Postモデルに
userメソッドを定義する
インスタンスメソッド
左の図のように、Postモデル内にその投稿に紐付いたuserインスタンスを戻り値として返すuserメソッドを定義しましょう。
■ ターミナルで以下のコマンドを実行してください
rails console
■ コンソールで以下のコマンドを実行してください
post = Post.find_by(id: 1)
post.user
quit
post.rb
class Post < ApplicationRecord
validates :content, {presence: true, length: {maximum: 140}}
validates :user_id, {presence: true}
# インスタンスメソッドuserを定義してください
def user
return User.find_by(id: self.user_id)
end
end
def show
@post = Post.find_by(id: params[:id])
# 以下の1行を、userメソッドを用いて書き換えてください
@user = @post.user
end
“>
<%= link_to(post.user.name, "/users/#{post.user.id}") %>
whereメソッド
where
ある条件に合致する「複数の」データを取得するには、whereメソッドを
用いる必要があります。whereメソッドでデータを取得した場合、それぞれの
データは配列に入っています。まずは「rails console」を用いて
whereメソッドを実際に使ってみましょう!
user.rb
# インスタンスメソッドpostsを定義してください
def posts
return Post.where(user_id: self.id)
end
■ ターミナルで以下のコマンドを実行してください
rails console
■ コンソールで以下のコマンドを実行してください
user = User.find_by(id: 1)
user.posts
quit
ユーザー詳細に投稿を表示しよう
投稿を表示しよう
@user.postsを用いて、各投稿をそれぞれ表示しましょう。
whereメソッドで取得した値は配列に入っていますので、
ビュー側でeach文を用いて、1つずつ投稿を表示していきます。
show.html.erb
<% @user.posts.each do |post| %>
<%= link_to(post.content, "/posts/#{post.id}") %>
<% end %>
投稿者のみに編集・削除
リンクを表示しよう
ログインしているユーザーが、その投稿の作成者である場合のみ、
投稿の編集・削除のリンクを表示するようにしましょう。
以下の図では「@post.user」のidと、「@current_user」のidを比較し、
等しい場合にのみ編集・削除リンクを表示しています。
■ ターミナルで以下のコマンドを実行してください
rails console
■ コンソールで以下のコマンドを実行してください
posts = Post.where(user_id: 1)
posts[0].content
quit
Userモデルにpostsメソッドを定義する
インスタンスメソッド
左の図のように、Userモデル内にユーザーに紐付いた
Postインスタンスを戻り値として返すpostsメソッドを定義しましょう。
show.html.erb
<% if @post.user_id == @current_user.id %>
<% end %>
投稿の編集・削除を制限しよう
before_actiononly
今回は、投稿に紐づくユーザーと現在ログインしているユーザーが異なる
かどうかを比べるために、postsコントローラ内に「ensure_correct_user」
というメソッドを用意します。
before_actionを用いることで、このメソッドをedit、update、destroyの
それぞれのアクションで適用しましょう。
posts_controller.rb
# before_actionでensure_correct_userメソッドを指定してください
before_action :ensure_correct_user, {only: [:edit, :update, :destroy]}
# ensure_correct_userメソッドを定義してください
def ensure_correct_user
@post = Post.find_by(id: params[:id])
if @post.user_id != @current_user.id
flash[:notice] = “権限がありません”
redirect_to(“/posts/index”)
end
end