denisov_2023
@denisov_2023 (デニソフ)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Ajax非同期処理のいいねの投稿のみ挙動しない

□解決したいこと

いいね機能を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

□追加で調べたこと

同様の質問者様がいらっしゃったので参考にしました。

https://teratail.com/questions/289782

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上でのエラーとなってしまいました。

0

1Answer

_like_partial.html.erb

<%= link_to tip_like_path(@tip),method: :delete, remote: true do %>

<%= link_to tip_like_path(id: @tip.likes[0].id, tip_id: @tip.id),method: :delete, remote: true do %>
としたらできました。

原因はidを指定していなかったためでした。

0Like

Your answer might help someone💌