\ プログラミング学習奮闘記録 /

Progate学習メモ Ruby on Rails5【SNSを作る⑧〜投稿とユーザーの紐付け〜】

目次

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のそれぞれのアクションで適用する
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次