プログラミングの勉強日記
2020年7月23日 Progate Lv.215
Ruby on RailsⅨ
postsテーブルにuser_idのカラムの追加
各投稿にどのユーザがその投稿を作成したかという情報を持たせるためにpostsテーブルにuser_idというカラムを用意する。rails generate migration
を用いてadd_user_id_to_posts
というファイル名のマイグレーションファイルを作成し、マイグレーションファイルを変更してrails db:migrate
を実行する。
$ rails generate migration add_user_id_to_posts
マイグレーション変更後
$ rails db:migrate
class AddUserIdToPosts < ActiveRecord::Migration[5.0]
def change
add_column :posts, :user_id, :integer
end
end
誰が投稿したかという情報は必要不可欠なので、user_idにバリデーションを設定する。
class Post < ApplicationRecord
validates :user_id, {presence: true}
end
新規投稿をログインユーザに紐づけ
新規投稿作成時にuser_idの値を入れて保存する。投稿したユーザは現在ログインしているユーザ(@current_user
)
def create
@post=Post.new(
content: params[:content}
user_id: @current_user.id
)
end
投稿でユーザ情報の表示
ユーザ名やユーザ画像を表示するためには、user_idカラムの値からそのユーザの情報を取得する。投稿詳細ページなので、postsコントローラのshowアクション内で@post.user_id
を用いてそのidに該当するユーザ情報をデータベースから取得。
def show
@post=Post.find_by(id: params[:id])
@user=User.fnd_by(id: @post.user_id)
end
<div class="post_user_name">
<img src="<%= "/user_images/#{@user.image_name}" %>">
<%= link_to(@user.name, "/users/#{@user.id}") %>
</div>
インスタンスメソッドの定義
投稿に紐づくユーザの情報は良く使うので簡単に使えるようにメソッドにする。Railsではモデル内にインスタンスメソッドを定義できる。Postモデル内にその投稿に紐づいたuserインスタンスを戻り値として返すuserメソッドを作成する。
class Post < ApplicationRecord
def user
#インスタンスメソッド内でselfはインスタンス自身を指す。
return Post.find_by(id: self.id)
end
end
ユーザ詳細ページに投稿を表示
ユーザ詳細ページにそのユーザが作成した投稿を一覧で表示する。あるユーザに紐づいている投稿を取得する。find_byメソッドではその条件に合致するデータを1件だけ取得する。複数のデータを取得するためにはwhereメソッドを用いる。whereメソッドで取得した場合、それぞれのデータは配列で入っている。
class User < ApplicationRecord
def posts
return Post.where(user_id: self.id)
end
end
<% @user.posts.each do |post| %>
#ここに表示する内容を書く
<% end %>
投稿者のみが編集・削除できるようにする
ログインしているユーザがその投稿の作成者である場合のみ編集・削除のリンクを表示する。
<% if @post.user_id == @current_user.id %>
<%= link_to("編集", "/posts/#{@post.id}/edit") %>
<%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>
<% end %>
このままだとURLに直接アクセスすると編集・削除できてしまうので、これの対処をする。
class PostsController < ApplicationController
before_action :ensure_correct_user, {only:[:edit,:update,:destroy]
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
end