Ajax非同期処理のいいねの投稿のみ挙動しない
Q&A
Closed
□解決したいこと
いいね機能をAjaxにて実装したいと考えております。
https://gyazo.com/4981862a465699475bcfec773839c50d
以上の動画のようにいいねの解除はできるのですが、いいねを新しく投稿すると
ActionView::Template::Error (No route matches {:action=>"destroy", :controller=>"likes", :tip_id=>#<Tip id: 25, title: "テスト", category_id: 4, description: "Lorem ipsum dolor sit amet, consectetur adipiscing...", user_id: 1, created_at: "2021-05-20 13:57:31", updated_at: "2021-05-27 22:59:36", image: nil>}, missing required keys: [:id]):
1: <% if user_signed_in? %>
2: <% if current_user.already_liked?(@tip)%>
3: <%= link_to tip_like_path(@tip),method: :delete, remote: true do %>
4: <i class="fas fa-heart unlike-btn"></i>
5: <% end %>
6: <% else %>
app/views/likes/_like_partial.html.erb:3
app/views/likes/create.js.erb:1
以上のエラーが発生します。
rails での実装に挙動は問題ないのですが、非同期処理のいいねを押す挙動だけうまくいきません。
□仮説及び調べたこと
エラー構文の中で:action=>"destroy"が行われています。今回は新たにいいねを押すため、destroyではなくpostが起動するはずです。
つまり、2行目
<% if current_user.already_liked?(@tip)%>
が正常に起動しておらず、条件分岐ができていないと考えました。
likes_controllerでbinding.pryで値を取得して確認しました。
def create
@like = current_user.likes.new(tip_id: params[:tip_id])
@tip = Tip.find_by(id: params[:tip_id])
binding.pry
@like.save
end
[1] pry(#<LikesController>)> current_user.already_liked?(@tip)
Like Exists? (0.4ms) SELECT 1 AS one FROM `likes` WHERE `likes`.`user_id` = 2 AND `likes`.`tip_id` = 25 LIMIT 1
↳ app/models/user.rb:17:in `already_liked?'
=> false
current_user.already_liked?(@tip)を打ち込んで確認しましたが、
値はfalseとなりました。つまり、現在のユーザーはいいねをしていない状態ということです。
これからいいねをしようとしている状態ですので、状態としては問題ないはずです。
しかし、actionはdestroyとなっており、if current_user.already_liked?(@tip)がtrueである場合の挙動をしております。
なぜこのような挙動となるかがわかりません。
もし、何か原因がお分かりの方がいらっしゃいましたらご教示ただきたくお願い申し上げます。
□環境
rails (6.0.3.7)
ruby 2.6.5
□問題のコード
tips/show.html
<div class = "wrapper">
<%= render "shared/header" %>
<div class="main-tips-show">
<div class="like-show" id='likes_buttons_<%= @tip.id %>'>
<%= render partial:'likes/like_partial' %>
</div>
<以下省略>
_like_partial/html.erb
<% if user_signed_in? %>
<% if current_user.already_liked?(@tip)%>
<%= link_to tip_like_path(@tip),method: :delete, remote: true do %>
<i class="fas fa-heart unlike-btn"></i>
<% end %>
<% else %>
<%= link_to tip_likes_path(@tip),method: :post, remote: true do %>
<i class="far fa-heart like-btn" ></i>
<% end %>
<% end %>
<% else %>
<i class="far fa-heart like-btn" ></i>
<% end %>
<p><%=@tip.likes.count %> </p>
create.js.erb 及び destroy.js.erb
$('#likes_buttons_<%= @tip.id %>').html("<%= j(render partial: 'likes/like_partial') %>");
likes_controller.rb
class LikesController < ApplicationController
def create
@like = current_user.likes.new(tip_id: params[:tip_id])
@tip = Tip.find_by(id: params[:tip_id])
binding.pry
@like.save
end
def destroy
@like = Like.find_by(tip_id: params[:tip_id], user_id: current_user.id)
@like.destroy
@tip = Tip.find_by(id: params[:tip_id])
end
end
user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :nickname, presence: true, length: { maximum: 6 }
validates :password, presence: true, format: { with: /[a-z\\d]{6,}/i, message: 'は半角英数6文字以上としてください' }
with_options presence: true, format: { with: /\\A[ぁ-んァ-ヶ一-龥々]+\\z/, message: 'には全角文字を使用してください' } do
validates :last_name
validates :first_name
end
has_many :tips
has_many :comments
has_many :likes
has_many :liked_tips, through: :likes, source: :tip
def already_liked?(tip) #←すでにいいねしているかの記述
self.likes.exists?(tip_id: tip.id)
end
end
□追加で調べたこと
同様の質問者様がいらっしゃったので参考にしました。
deleteにlikeのidが引き継がれていないのが原因かもしれないと思い、
<%= link_to tip_like_path(@tip,@like),method: :delete, remote: true do %>
とし、@likeと@tip の2つのidを取ろうと思いましたが、うまく行きませんでした。
likeのidがnilでした。
ActionView::Template::Error (No route matches {:action=>"destroy", :controller=>"likes", :id=>nil, :tip_id=>"25"}, missing required keys: [:id]):
1: <% if user_signed_in? %>
2: <% if current_user.already_liked?(@tip)%>
3: <%= link_to tip_like_path(@tip, @like),method: :delete, remote: true do %>
4: <i class="fas fa-heart unlike-btn"></i>
5: <% end %>
6: <% else %>
app/views/likes/_like_partial.html.erb:3
app/views/tips/show.html.erb:5
こちらのエラーはrails上でのエラーとなってしまいました。