質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

2回答

1238閲覧

Rails6におけるいいねの非同期処理のエラー

husqy

総合スコア2

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2021/07/11 13:15

編集2021/07/13 13:55

ご覧いただきありがとうございます。
長文で大変申し訳無いのですが、以下のエラーで困っており、
ご教授いただければ幸いです。

用途の都合上、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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

husqy

2021/07/13 13:55

ありがとうございます! controllerを載せさせて頂きました! お手数をおかけしますが、ご確認お願いします。
guest

回答2

0

自己解決

js.erbの引数の書き方が間違ってました。

投稿2021/07/14 08:09

husqy

総合スコア2

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

いいねを押したとき というのでそのつもりで質問を読んでいたら エラーでは destroy になっている。 いいねを外すときのエラーですね?

def destroy の road を @road にしてください

投稿2021/07/13 22:44

winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

husqy

2021/07/14 04:45

ご回答ありがとうございます! 説明が下手で申し訳ありません。 正確に言うと、いいね/いいね外し共に非同期が作動しません。 ページリロードすると反映されます。 > def destroy の road を @road にしてください こちらはlikes_controllerのことでしょうか? すでに@roadとなっておりますが、上記のように非同期処理が作動しません。 お手数をおかけしますが、ご確認いただければ幸いです。
winterboum

2021/07/14 07:10

def destroy road = Road.find(params[:id]) road.destroy end なってません
husqy

2021/07/14 08:09

原因、自己解決できました! アドバイスを頂いてありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問