Posted at

Progate rails道場コースⅣ 攻略メモ前編

いよいよrails道場コースもラストです!!

だいぶ複雑になってきますが地道に頑張りましょう!


3/14 新規投稿をログイン中のユーザーと紐付ける

初めに、投稿詳細ページに、投稿に紐づくユーザー名とユーザー画像を表示していきます。

imgタグとlink_toメソッドを使って実装するのですが、その前に投稿にユーザーのデータを紐付けてあげましょう。


新規投稿とログインユーザーを紐付ける

まずは新規投稿のcreateアクションをいじっていきます。

現在createアクションは、投稿された内容(content属性)を受け取るのみですが、ここに投稿したユーザーのデータも追加してあげます。

  def create

@post = Post.new(content: params[:content],
user_id: @current_user.id)

3行目が追加したコードです。@postに、user_id属性を追加します。

前章で実装した、@current_userを使って、ログイン中のユーザー情報を取得し、投稿内容と一緒に飛ばします。

ちなみに@current_userは、全コントローラーで共通して使えるメソッドを定義できるapplication_controllerで定義されます。その後before_actionという機能によって、createアクションの実行前に自動で動くようになってます。

つまり現在、@current_userというインスタンス変数で、いつでもログイン中のユーザー情報を取得できるということですね。うーん便利。

これで投稿データの中に投稿者データも含まれるようになりました。


投稿詳細ページにユーザー情報を表示させる

次は投稿詳細ページに、投稿者のデータを表示させましょう。

現在showアクションには、@postのデータを渡すコードしかありません。

この@postの中にある、user_idという先ほど作った属性を利用して、ユーザーデータを表示します。

@user = User.find_by(id: @post.user_id)

👆find_byメソッドを使い、変数@post内のuser_idを取得し、userテーブルのidカラムから一致するユーザーデータを@userへと代入。

これで、postとuserという違う種類のデータを紐づけることができました!


Postモデルに紐付いたuserを探すメソッドを作る。

コードを簡潔にするために、上で書いた機能をインスタンスメソッド化します。

モデル内にインスタンスメソッドを定義することにより、そのメソッドをインスタンスに対して利用できるようになります。

/models/post.rb

def user

return User.find_by(id: self.user_id)
end

つまり、上記のuserメソッドををPostモデル内に定義することにより、Postコントローラーで下記のように@postというインスタンス変数に対して使えるようになります。(3行目)

selfの部分は、そのインスタンス変数そのものを表すため、ここでは呼び出し元の@postが入ります。

def show

@post = Post.find_by(id: params[:id])
@user = @post.user
end


ビューに反映しよう

やっとこさ投稿者データを表示する準備が整いました。

投稿詳細ページをいじって、投稿者の画像と投稿者のプロフィールに飛ぶリンクを作ってあげましょう。

  <img src="<%= "/user_images/#{@user.image_name}" %>">

<%= link_to(@user.name, "/users/#{@user.id}")%>

@userには、投稿データ内のuser_idから引っ張ってきたユーザーデータが入っているため、image_nameやid、emailなどのuserモデル固有の属性を表示することができます。

はぁ〜長かった!!


4/14 投稿一覧ページにユーザー情報を表示しよう

ここで先程作ったインスタンスメソッドuserが大活躍します。

<% @posts.each do |post| %>

<div class="posts-index-item">
<div class="post-left">
<img src="<%= "/user_images/#{post.user.image_name}" %>">
</div>
<!-- 以下省略 -->

ここの4行目がカギです。

変数展開の中のpostは、@posts(投稿のデータ全部)から一つずつ渡されてくるものですが、それに対して先ほど定義したuserメソッドを使うことが出来ます。

そのためpost.user.image_nameは、

@postにuserメソッドを用いてユーザーデータを取得した後、ユーザーデータの属性のimage_nameを引っ張ってくることになります。

同じように、

<%= link_to( "#{post.user.name}", "/users/#{post.user.id}" ) %>

このように書くことで、ブロックで渡されたデータ(post)から、違う種類のデータ(user)の中身を引っ張ってくることができます!


6/14 投稿の編集と削除を制限しよう

現在のままでは、誰でも投稿データの編集と削除が行える状態なので、本人以外出来ないようにしていきます。

まずは投稿詳細ページにある、編集と削除のリンクを本人以外に表示されないようにしましょう。

/views/show.html.erb

<% if @user.id == @current_user.id %>

<%= link_to("編集", "/posts/#{@post.id}/edit") %>
<%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>
<% end %>

このようにif文で囲むと、条件式にマッチする場合のみ表示されないようになります。

条件式の@user.id == @current_user.idで、表示している投稿の投稿者と、ログインしているユーザーが等しいか確認しています、

@userのデータがどこから来ているのかわからなければ、一度post_contrlloerのshowアクションを見に行ってみるといいでしょう。

今回のコースはやや長めなため、記事を3つに分けます。

次回はいいね機能を実装します。