【Ruby on Rails】投稿したユーザーのみ編集&削除を表示させる実装奮闘記
Railsに対する基本理解が深まった経験の記録。
(途中起きたエラー内容および対応は割愛)
実現したいこと
- 投稿したユーザーのみに編集&削除を表示させる
※view表示にフォーカス
(他ユーザーからの編集&削除権限の制限実装については割愛)
本実装までの考え方
- if文を使ってviewの表示を使い分る
- 既存テーブルにカラムを追加
- Sorceryで使えるメソッド
- モデル同士の紐付け
- 投稿時に投稿者のuser_idを追加
開発環境
前提
- Sorceryを使ったユーザー新規登録&ログイン&ログイン機能(user)
- 新規投稿&編集&削除機能(post)
以上実装済み
詳細
1. if文を使ってviewの表示を使い分ける
はじめに色々ググっていると最終的に以下のコードが通れば上手く表示されるんかな〜という考えにたどり着く。
<% @posts.each do |post| %> <tr> ・・・ <% if post.user_id == current_user.id %> <td><%= link_to 'Edit', edit_post_path(post) %></td> <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td> <% end %> </tr> <% end %> ・・・
2. 既存テーブルにカラムを追加
post.user_id
とcurrent_user.id
の数字が一致すれば、、
でもpostsテーブルにuser_idカラムなんてあったっけ?
db/migrate/schema.rb
・・・ create_table "posts", force: :cascade do |t| t.string "title" t.text "content" t.datetime "created_at", null: false t.datetime "updated_at", null: false end ・・・
無いッスね。
つまり追加しないといけないので、、
$ rails g migration AddUserIdToPosts user_id:string
(既存テーブルのカラム追加してくれる優しい奴)
をコマンド実行して自動生成されたdb/migrate/XXXXXXXXXXXXXX_add_user_id_to_posts.rb
に
・・・ def change add_column :posts, :user_id, :integer end ・・・
を追記して$ rails db:migrate
db/migrate/schema.rb
(変更後)
・・・ create_table "posts", force: :cascade do |t| t.string "title" t.text "content" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.integer "user_id" end ・・・
このt.integer "user_id"
が増えたことでカラムの追加が完了!
3. Sorceryで使えるメソッド
current_user.id
というのはSorceryに元々備わっているメソッドで
ログイン中のユーザーIDを拾ってくれる便利な奴とのこと(有り難い!)
4. モデル同士の紐付け
ユーザー1人に対して投稿は複数存在するから「1対多」の関係にあるため
app/models/post.rb
に
class Post < ApplicationRecord belongs_to :user end
app/models/user.rb
に
class User < ApplicationRecord authenticates_with_sorcery! ・・・ has_many :posts, dependent: :destroy end
をそれぞれ追記すると上手く紐付いてくれました◎
(dependent: :destroy
はuserを削除した時紐付いたpostsも一緒に消しまっせってことらしい)
5. 投稿時に投稿者のuser_idを追加
最後に、
app/controllers/posts_controllers.rb
で新規投稿時にログインユーザーのIDがuser_idに追加されるように修正。
(変更前)
・・・ def create @post = Post.new(post_params) ・・・
(変更後)
・・・ def create @post = current_user.posts.build(post_params) ・・・
user.rbに「has_many :posts」があると「Userインスタンス.posts.build」というメソッドが使えるらしい◎
以上で実装完了!
大作になってしまった。。