ご覧いただきありがとうございます。
長文で大変申し訳無いのですが、以下のエラーで困っており、
ご教授いただければ幸いです。
用途の都合上、roadという名前にしていますが、機能的には投稿機能です。
前提・実現したいこと
Ruby/Railsでいいね機能を実装しており、
機能自体は実装できたのですが、一つだけバグがあり修正方法がわからないでおります。
投稿の一覧画面(index)/詳細画面(show)において、いいねボタン(ハートアイコン)を押すと非同期でいいねボタンが色付き/色なしに切り替わる機能を実装したい。
発生している問題・エラーメッセージ
index/showページで「いいね」を押しても反応がないが、ページリロードで反映される。
押したとき、コンソール上で以下のエラーが発生している。
Started DELETE "/roads/1/likes" for ::1 at 2021-07-11 22:05:31 +0900 Processing by LikesController#destroy as JS Parameters: {"road_id"=>"1"} User Load (1.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]] Like Load (1.4ms) SELECT "likes".* FROM "likes" WHERE "likes"."user_id" = $1 AND "likes"."road_id" = $2 LIMIT $3 [["user_id", 2], ["road_id", 1], ["LIMIT", 1]] ↳ app/controllers/likes_controller.rb:12:in `destroy' TRANSACTION (0.9ms) BEGIN ↳ app/controllers/likes_controller.rb:12:in `destroy' Like Destroy (1.0ms) DELETE FROM "likes" WHERE "likes"."id" = $1 [["id", 7]] ↳ app/controllers/likes_controller.rb:12:in `destroy' Road Update All (1.1ms) UPDATE "roads" SET "likes_count" = COALESCE("likes_count", 0) - $1 WHERE "roads"."id" = $2 [["likes_count", 1], ["id", 1]] ↳ app/controllers/likes_controller.rb:12:in `destroy' TRANSACTION (1.4ms) COMMIT ↳ app/controllers/likes_controller.rb:12:in `destroy' Road Load (1.0ms) SELECT "roads".* FROM "roads" WHERE "roads"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] ↳ app/controllers/likes_controller.rb:13:in `destroy' Rendering likes/destroy.js.erb Rendered likes/destroy.js.erb (Duration: 5.0ms | Allocations: 4573) Completed 500 Internal Server Error in 26ms (ActiveRecord: 8.3ms | Allocations: 10942) ActionView::Template::Error (undefined local variable or method `road' for #<ActionView::Base:0x0000000000aca8> Did you mean? @road): 1: document.getElementById('road-<%= road.id %>').innerHTML = '<%= j render("roads/dislike") %>' app/views/likes/destroy.js.erb:1
該当のソースコード
ERB
1<#% index.html.erb %> 2 3<h1>投稿一覧</h1> 4<%= link_to '新規投稿', new_road_path, class: 'btn' %> 5 6<% @roads.each do |road| %> 7 8 (略) 9 10 <%= render partial: 'road', locals: {road: road} %> 11 12 (略) 13 <% end%> 14<% end %>
ERB
1<#% show.html.erb %> 2 3 (略) 4<%= render 'road', {road: @road} %> 5 (略)
ERB
1<#% _road.html.erb %> 2 3<p id="road-<%= @road.id %>"> 4 <% if road.liked_by?(current_user) %> 5 <%# 「いいね!」済み %> 6 <%= render "like", road: road %> 7 <% else %> 8 <%# 「いいね!」していない %> 9 <%= render "dislike", road: road %> 10 <% end %> 11</p>
ERB
1<%# _like.html.erb %> 2 3<%= link_to road_likes_path(road), class: "like-link", method: :delete, remote: true do %> 4 <i class="fas fa-heart unlike-btn"></i> 5<% end %> 6<%= road.likes_count %>
ERB
1<%# _dislike.html.erb %> 2 3<%= link_to road_likes_path(road), class: "like-link", method: :post, remote: true do %> 4 <i class="far fa-heart like-btn"></i> 5<% end %> 6<%= road.likes_count %>
Ruby
1## Road.rb 2 3class Road < ApplicationRecord 4 has_many_attached :road_images 5 has_many :comments 6 has_many :likes, dependent: :destroy 7 has_many :liked_users, through: :likes, source: :user 8 belongs_to :user 9 10 def liked_by?(user) 11 likes.any?{ |like| like.user_id == user.id } 12 end 13end
Ruby
1## like.rb 2 3class Like < ApplicationRecord 4 belongs_to :user 5 belongs_to :road, counter_cache: :likes_count 6 7 validates :user_id, uniqueness: { 8 scope: :road_id, 9 message: "は同じ投稿に2回以上いいねはできません", 10 } 11end
JavaScript
1// create.js.erb 2document.getElementById('road-<%= @road.id %>').innerHTML = '<%= j render("roads/like") %>' 3
JavaScript
1// destroy.js.erb 2document.getElementById('road-<%= @road.id %>').innerHTML = '<%= j render("roads/dislike") %>'
Ruby
1# roads_controller.rb 2 3class RoadsController < ApplicationController 4 5 def index 6 @roads = Road.includes(:user, :likes).order(:created_at) 7 end 8 9 def show 10 @road = Road.find(params[:id]) 11 @comments = @road.comments 12 @comment = Comment.new 13 end 14 15 def new 16 @road = Road.new 17 end 18 19 def create 20 @road = Road.create(road_params) 21 end 22 23 def edit 24 @road = Road.find(params[:id]) 25 end 26 27 def update 28 road = Road.find(params[:id]) 29 if params[:road][:road_image_ids] 30 params[:road][:road_image_ids].each do |road_image_id| 31 image = road.road_images.find(road_image_id) 32 image.purge 33 end 34 end 35 if road.update(road_params) 36 flash[:success] = "編集しました" 37 redirect_to roads_url 38 else 39 render :edit 40 end 41 end 42 43 def destroy 44 road = Road.find(params[:id]) 45 road.destroy 46 end 47 48 private 49 def road_params 50 params.require(:road).permit(:title, :description, :latitude, :longitude, :content, road_images: []).merge(user_id: current_user.id) 51 end 52end
Ruby
1# likes_controller.rb 2 3class LikesController < ApplicationController 4 def create 5 current_user.likes.create!(road_id: params[:road_id]) 6 @road = Road.find(params[:road_id]) 7 end 8 9 def destroy 10 11 current_user.likes.find_by(road_id: params[:road_id]).destroy! 12 @road = Road.find(params[:road_id]) 13 end 14end 15
試したこと
エラーの指示通りにjs.erbのroadを@roadに修正修正すると、
以下のエラーが発生。
ActionView::Template::Error (undefined local variable or method `road' for #<ActionView::Base:0x0000000000b040> Did you mean? @road): 1: <%= link_to road_likes_path(road), class: "like-link", method: :delete, remote: true do %> 2: <i class="fas fa-heart unlike-btn"></i> 3: <% end %> 4: <%= road.likes_count %>
_like.html.erbと_dislike.html.erbのroadを@roadに修正すると、
index.html.erbを開いた時に以下のエラー画面になる。
*showは正常に表示され、いいねボタンも非同期で動作するようになる。
ActionController::UrlGenerationError in Roads#index Showing /Users/hiroto/Desktop/Portfolio/Tamari-Ba/app/views/roads/_like.html.erb where line #1 raised: No route matches {:action=>"destroy", :controller=>"likes", :road_id=>nil}, possible unmatched constraints: [:road_id] Did you mean? road_likes_url Extracted source (around line #1): <%= link_to road_likes_path(@road), class: "like-link", method: :delete, remote: true do %> <i class="fas fa-heart unlike-btn"></i> <% end %> <%= @road.likes_count %> Trace of template inclusion: #<ActionView::Template app/views/roads/_road.html.erb locals=["road"]>, #<ActionView::Template app/views/roads/index.html.erb locals=[]>
補足情報(FW/ツールのバージョンなど)
Ruby: 2.7.2
Rails: 6.1.3
回答2件
あなたの回答
tips
プレビュー