7
8

More than 3 years have passed since last update.

投稿とユーザの紐づけ(Ruby on Rails)

Posted at

プログラミングの勉強日記

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
2020..._add_user_id_to_posts.rb
class AddUserIdToPosts < ActiveRecord::Migration[5.0]
  def change
    add_column :posts, :user_id, :integer
  end
end

誰が投稿したかという情報は必要不可欠なので、user_idにバリデーションを設定する。

models/posts.rb
class Post < ApplicationRecord
  validates :user_id, {presence: true}
end

新規投稿をログインユーザに紐づけ

 新規投稿作成時にuser_idの値を入れて保存する。投稿したユーザは現在ログインしているユーザ(@current_user)

posts_controller.rb
def create
  @post=Post.new(
    content: params[:content}
    user_id: @current_user.id
  )
end

投稿でユーザ情報の表示

 ユーザ名やユーザ画像を表示するためには、user_idカラムの値からそのユーザの情報を取得する。投稿詳細ページなので、postsコントローラのshowアクション内で@post.user_idを用いてそのidに該当するユーザ情報をデータベースから取得。

posts_controller.rb
def show
  @post=Post.find_by(id: params[:id])
  @user=User.fnd_by(id: @post.user_id)
end
posts/show.html.erb
<div class="post_user_name">
  <img src="<%= "/user_images/#{@user.image_name}" %>">
  <%= link_to(@user.name, "/users/#{@user.id}") %>
</div>

インスタンスメソッドの定義

 投稿に紐づくユーザの情報は良く使うので簡単に使えるようにメソッドにする。Railsではモデル内にインスタンスメソッドを定義できる。Postモデル内にその投稿に紐づいたuserインスタンスを戻り値として返すuserメソッドを作成する。

models/post.rb
class Post < ApplicationRecord
  def user
    #インスタンスメソッド内でselfはインスタンス自身を指す。
    return Post.find_by(id: self.id)
  end
end

ユーザ詳細ページに投稿を表示

 ユーザ詳細ページにそのユーザが作成した投稿を一覧で表示する。あるユーザに紐づいている投稿を取得する。find_byメソッドではその条件に合致するデータを1件だけ取得する。複数のデータを取得するためにはwhereメソッドを用いる。whereメソッドで取得した場合、それぞれのデータは配列で入っている。

models/user.rb
class User < ApplicationRecord
  def posts
    return Post.where(user_id: self.id)
  end
end
users/show.html.erb
<% @user.posts.each do |post| %>
  #ここに表示する内容を書く
<% end %>

投稿者のみが編集・削除できるようにする

 ログインしているユーザがその投稿の作成者である場合のみ編集・削除のリンクを表示する。

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

このままだとURLに直接アクセスすると編集・削除できてしまうので、これの対処をする。

posts_controller.rb
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
7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8