user_idを用いて投稿とユーザーを紐付ける
各投稿に「どのユーザーがその投稿を作成したか」という情報を
持たせるために、postsテーブルにuser_idというカラムを用意する。
《ターミナル》
$ rails g migration add_user_id_to_posts
マイグレーションファイルの中身のコードを書いてから、「rails db:migrate」を実行する
《マイグレーションファイル》
def change
add_column :posts, :user_id, :integer
end
- integerは整数を扱うデータ型
user_idのバリデーション
postsテーブルにuser_idカラムが追加されたら、バリデーションを設定する
《models/posts.rb》
validates :user_id, {presence: true}
- 誰が投稿したか、という情報は必ずあるべきなので、user_idに「presence: true」を指定する
- 「presence: true」は指定された値が存在することを検証するバリデーション
新規投稿をログインユーザーに紐づける
投稿したユーザーのidを紐づける
新規投稿作成時に、user_idの値をいれて保存するようにする。
投稿したユーザーは、現在ログインしているユーザーなので、「@current_user.id」で取得できる。
《posts.controller》
@post = Post.new(
contents: params[:contents]
user_id: @current_user.id ←新規投稿時に、投稿したユーザーのIDを加える
)
- newメソッドの部分で、user_idの値として「@current_user.id」をいれる
投稿にユーザー情報を表示する
user_idからユーザー情報を取得する
ユーザー名やユーザー画像を表示するためには、user_idカラムの値から、そのユーザーの情報を取得する必要がある。
投稿詳細ページでユーザー名や画像を表示するので、postsコントローラのshowアクション内で、「@post.user_id」を用いて、そのidに該当するユーザーの情報をデータベースから取得する。
《posts_controller》
def show
@post = Post.find_by(id: params[:id])
@user = User.find_by(id: @post.user_id)
end
- @post.user_idの値から該当するidのユーザー情報を取得する
ユーザー画像とユーザー名を表示する
アクション側で定義した変数@userを用いて、ユーザー画像とユーザー名を表示する
《posts/show.html》
<div class=”post-user-name”>
<img src=”<%= “user_images/#{@user.image_name}”%>”>
<%= link_to(@user.name,”/users/#{@user.id}“)%>
</div>
- 画像はpublic/user_imagesフォルダに保存されているので、src属性の値を「/user_images/ファイル名」とする必要がある
- ユーザー名を表示して、リンク先はuserの詳細ページ
インスタンスメソッドを定義する
投稿に紐付くユーザーの情報はこれからもよく使っていくから、簡単に使えるようメソッドにする。
modelにインスタンスメソッドを定義する
Railsではモデル内にインスタンスメソッドを定義することができる
【例】
《models/posts.rb》
def hello
puts “我が名はアシタカ”
end
《ターミナル》
$ rails console
post = Post.find_by(id:1) → postsモデルのインスタンスを取得する
post.hello → postsモデル内のhelloメソッド「我が名はアシタカ」が呼び出される
【具体的には】
《models/posts.rb》
def user
return User.find_by(id: self.user_id)
end
- Postモデル内にその投稿に紐付いたuserインスタンスを戻り値として返すuserメソッドを定義する
- インスタンスメソッド内で、selfはそのインスタンス自身を指す
《ターミナル》
$ rails console
post = Post.find_by(id:1)
post.user → 投稿に紐づいているユーザー情報がターミナルに表示される
インスタンスメソッドを用いる
先ほど Post モデルに定義した user メソッドを用いて、投稿詳細ページのコードを書き換える
《posts.controller.rb》
def show
@post = Post.find_by(id: params[:id])
@user = User.find_by(id: @post.user_id)
end
|
| Post モデルに定義した user メソッドを用いて、投稿詳細ページのコードを書き換えると
↓
def show
@post = Post.find_by(id: params[:id])
@user = @post.user
end
投稿一覧にもユーザー情報を表示する
投稿詳細ページと同じように、user メソッドを用いる
《index.html.tb》
<img src=”<%= “user_images/#{@user.image_name}”%>”>
|
| user メソッドを用いて書き換え
↓
<div class="post-left">
<img src="<%= "/user_images/#{post.user.image_name}" %>">
</div>
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
<%= link_to(@user.name,"/users/#{@user.id}")%>
|
| user メソッドを用いて書き換え
↓
<post-right">
<div class="post-user-name">
<%= link_to(post.user.name,"/users/#{post.user.id}")%>
</div>
ユーザー詳細ページに投稿を表示する
ここからはユーザー詳細ページにそのユーザーが作成した投稿を一覧で表示する。(Twitterのトップページみたいな感じ)
ユーザーに紐づく【複数の】投稿を取得する whereメソッド
ある条件に合致する「複数の」データを取得するには、whereメソッドを用いる必要がある
whereメソッドでデータを取得した場合、それぞれのデータは配列に入っている
ターミナルで使ってみると、、、
《ターミナル》
$ rails console
posts = Post.where(user_id:1) → ユーザーIDが1である投稿を全て取得
=> [◯,△,⬛︎、、、] → ユーザーIDが1である投稿の配列
posts[0].content → 配列のインデックス番号が0の投稿(一番最初の投稿)のみ取得する
これを利用して、ユーザーに紐付く投稿をまとめて取得する「posts メソッド」を User モデルに定義する
《models/user》
def posts
return Post.where(user_id: self.id)
end
Userモデル内にユーザーに紐付いた
Postインスタンスを戻り値として返すpostsメソッドを定義する
《ターミナル》
$ rails console
user = User.find_by(id:1)
user.posts → postsメソッドを呼び出せる
ユーザー詳細ページにそのユーザーが作成した投稿を一覧で表示する
@user.postsを用いて、各投稿をそれぞれ表示する
whereメソッドで取得した値は配列に入っているので、
ビュー側でeach文を用いて、1つずつ投稿を表示していく。
《users/show.html》
<% @user.posts.each do |post| %> ↓以下、表示内容を書く
<div class=”post-left”>
<img src=”<%= “/user_images/#{post.user.image_name}” %>”>
</div>
<post-right”>
<div class=”post-user-name”>
<%= link_to(post.user.name,”/users/#{post.user.id}”)%>
</div>
<%= link_to(post.content, “/posts/#{post.id}”) %>
</div>
<% end %>
投稿者だけが編集できるようにする
その投稿を作成した人ではない場合に、編集・削除リンクを表示しないようにする
投稿者のみに編集・削除リンクを表示する
《posts/show.hyml》
<% if @post.user_id == @current_user.id %>
→ 投稿を作成したユーザーのidと、ログインしているユーザーのidが等しい場合
<%= link_to(“編集”,”/posts/#{@post.id}/edit”) %>
<%= link_to(“削除”,”/posts/#{@post.id}/destroy”,{method: “post”})%>
<% end %>
- 「@post.user」のidと、「@current_user」のidを比較し、等しい場合にのみ編集・削除リンクを表示
URLに直接アクセスしても編集できないようにする
投稿に紐づくユーザーと現在ログインしているユーザーが異なるかどうかを比べるために、
postsコントローラ内に「ensure_correct_user」というメソッドを用意する。
《posts.controller.rb》
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
- before_actionを用いることで、このメソッドをedit、update、destroyのそれぞれのアクションで適用する
コメント