Ruby on Rails5 IX

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.user.name, "/users/#{post.user.id}") %>

<%= 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 %>

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


<% 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

シェアする

  • このエントリーをはてなブックマークに追加

フォローする