前提・実現したいこと
今、Ruby on Railsで投稿に対するお気に入り(いいね)機能を実装しています。
実現したいこととしては、投稿の詳細ページにあるお気に入りのアイコンをクリックするとそのユーザーのお気に入りの投稿に追加され、
もう一度クリックするとお気に入りの投稿から外れるといった、ごく一般的なお気に入り機能を実装したいです。
そこで、以下のQiita記事の「Favoriteの実装(多対多)」を参考にし、コードを書きました。
【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】
前提として、ここでは投稿をpost_g
、お気に入りをfavorite
と定義しています。
また、今回の問題に関係あるかわかりませんが、UserモデルやPostGモデルにおいて、
投稿をしたユーザーをgiver
、投稿に申し込むユーザーをtaker
、
ユーザーが投稿した投稿をgiving_post_gs
、ユーザーが申し込んだ投稿をtaking_post_gs
と定義しています。
発生している問題・エラーメッセージ
発生している問題としては、お気に入りのアイコンをクリックしてもお気に入りが保存されないということです。
その原因を探るため、favorite_gs_controller.rb
のcreateアクション内でcreate!
と記述したところ、以下のエラーが出ました。
ActiveRecord::RecordInvalid in FavoriteGsController#create バリデーションに失敗しました: Post gを入力してください。
該当のソースコード
▼routes.rb
ruby
1Rails.application.routes.draw do 2 3 resources :posts_g do 4 resource :favorite_gs, only: [:create, :destroy] 5 end 6 7end
▼posts_g_controller.rb
ruby
1class PostsGController < ApplicationController 2 3 def show 4 @user = @post.giver 5 @post = PostG.find(params[:id]) 6 @user = @post.giver 7 @favorite = @post.favorite_gs.where(user_id: current_user.id) 8 end 9 10end
▼views/posts_g/show.html.haml
haml
1 .Post_main__Box 2 - unless user_signed_in? && @user.id == current_user.id 3 - if @favorite.empty? 4 = link_to posts_g_favorite_gs_path(@post.id), method: :post do 5 = icon('far', 'bookmark', class: "Post_bookmark") 6 - else 7 = link_to posts_g_favorite_cs_path(@post.id), method: :delete do 8 = icon('fas', 'bookmark', class: "Post_bookmark")
▼favorite_gs_controller.rb
ruby
1class FavoriteGsController < ApplicationController 2 def create 3 FavoriteG.create!(user_id: current_user.id, post_g_id: params[:post_g_id]) 4 redirect_to posts_g_path(params[:posts_g_id]) 5 end 6 7 def destroy 8 favorite = FavoriteG.find_by(post_g_id: params[:post_g_id], user_id: current_user.id) 9 favorite.destroy 10 redirect_to posts_g_path(params[:posts_g_id]) 11 end 12end
▼favorite_g.rb
ruby
1class FavoriteG < ApplicationRecord 2 belongs_to :user 3 belongs_to :post_g 4 validates_uniqueness_of :post_g_id, scope: :user_id 5end
▼user.rb
ruby
1class User < ApplicationRecord 2 3 has_many :giving_post_gs, foreign_key: "giver_id", class_name: "PostG", dependent: :destroy 4 5 has_many :post_g_takers, foreign_key: "taker_id", dependent: :destroy 6 has_many :taking_post_gs, through: :post_g_takers, source: :taking_post_g, dependent: :destroy 7 8 has_many :favorite_gs, dependent: :destroy 9 10end
▼post_g.rb
ruby
1class PostG < ApplicationRecord 2 3 belongs_to :giver, class_name: 'User', foreign_key: 'giver_id' 4 has_many :post_g_takers, dependent: :destroy 5 has_many :takers, through: :post_g_takers, dependent: :destroy 6 7 has_many :favorite_gs, dependent: :destroy 8 9end
▼schema.rb
ruby
1 create_table "favorite_gs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 2 t.integer "user_id" 3 t.integer "post_g_id" 4 t.datetime "created_at", precision: 6, null: false 5 t.datetime "updated_at", precision: 6, null: false 6 end
試したこと
-
paramsが送られていないのではないかと思い、エラー画面を確認するとparametersの中に
"post_g_id"=>"13"
ときちんと書かれていました。 -
モデルの書き方が間違っているのかと思い、Qiitaの記事を見直してみましたが、間違いがわかりませんでした。
-
favorite_g.rb
のbelongs_to :post_g
の行にoptional: true
を追加してみたらエラー画面は出なくなったのですが、favorite_gsテーブルにpost_g_idが空の状態で保存されるようになってしまいました。
補足情報(FW/ツールのバージョンなど)
Railsのバージョンは6.0.3.2です。
データベースはMySQL、ユーザー機能はdeviseを使っています。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/11 12:43