前提・実現したいこと
Rails初心者です。
Ruby on railsで、各ユーザーが投稿(Book)できるアプリを開発しています。
投稿一覧画面と投稿詳細画面に、非同期通信のいいね機能を実装しようとしていますが、ページをリロードしないと表示されません。
※備考
いいねは以下のように切り替わります。
いいね(0) <=> いいねを消す(1)
発生している問題・エラーメッセージ
Logには以下のようなメッセージが表示されました。
「undefined method `favorited_by?' 」とありますが、book.rbに定義しているので
原因がわかりません。
Started DELETE "/books/1/favorites" for 211.120.130.120 at 2021-12-24 06:11:36 +0000 Cannot render console from 211.120.130.120! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by FavoritesController#destroy as JS Parameters: {"book_id"=>"1"} [1m[36mUser Load (0.1ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?[0m [["id", 1], ["LIMIT", 1]] ↳ /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.5/lib/active_record/log_subscriber.rb:98 [1m[36mBook Load (0.1ms)[0m [1m[34mSELECT "books".* FROM "books" WHERE "books"."id" = ? LIMIT ?[0m [["id", 1], ["LIMIT", 1]] ↳ app/controllers/favorites_controller.rb:9 [1m[36mFavorite Load (0.2ms)[0m [1m[34mSELECT "favorites".* FROM "favorites" WHERE "favorites"."user_id" = ? AND "favorites"."book_id" = ? LIMIT ?[0m [["user_id", 1], ["book_id", 1], ["LIMIT", 1]] ↳ app/controllers/favorites_controller.rb:10 [1m[35m (0.1ms)[0m [1m[36mbegin transaction[0m ↳ app/controllers/favorites_controller.rb:11 [1m[36mFavorite Destroy (0.2ms)[0m [1m[31mDELETE FROM "favorites" WHERE "favorites"."id" = ?[0m [["id", 33]] ↳ app/controllers/favorites_controller.rb:11 [1m[35m (6.5ms)[0m [1m[36mcommit transaction[0m ↳ app/controllers/favorites_controller.rb:11 Rendering favorites/destroy.js.erb Rendered favorites/_favorite.html.erb (3.2ms) Rendered favorites/destroy.js.erb (5.8ms) Completed 500 Internal Server Error in 27ms (ActiveRecord: 7.2ms) ActionView::Template::Error (undefined method `favorited_by?' for nil:NilClass): 1: <% if book.favorited_by?(current_user) %> 2: <td><%= link_to book_favorites_path(book.id), method: :delete, remote: true do %> 3: ♥<%= book.favorites.count %> いいね</td> 4: <% end %> app/views/favorites/_favorite.html.erb:1:in `_app_views_favorites__favorite_html_erb___640992299850121874_69917787488560' app/views/favorites/destroy.js.erb:1:in `_app_views_favorites_destroy_js_erb___1919995251382630832_69917787431440'
該当のソースコード
views/favorites/create.js.erb
views/favorites/delete.js.erb
$("#favorites_buttons_<%= @books %>").html("<%= j(render partial: 'favorites/favorite', locals:{book: @books})%>");
favorites_controller.rb
def create book = Book.find(params[:book_id]) favorite = current_user.favorites.new(book_id: book.id) favorite.save end def destroy book = Book.find(params[:book_id]) favorite = current_user.favorites.find_by(book_id: book.id) favorite.destroy end end
views/favorites/_favorite.html.erb
<% if book.favorited_by?(current_user) %> <td><%= link_to book_favorites_path(book.id), method: :delete, remote: true do %> ♥<%= book.favorites.count %> いいね</td> <% end %> <% else %> <td><%= link_to book_favorites_path(book.id), method: :post, remote: true do %> ♡<%= book.favorites.count %> いいね</td> <% end %> <% end %>
views/books/show.html.erb
<div id="favorite_btn_<%= @books.id %>"> <%= render partial: 'favorites/favorite', locals: { book: @books} %> </div>
views/books/_index.html.erb
<div id="favorite_btn_<%= book.id %>"> <%= render partial: 'favorites/favorite', locals: { book: book} %> </div>
books_controller.erb
def show @books = Book.find(params[:id]) @user = @books.user @book = Book.new @book_comment = BookComment.new end def index @book = Book.new @books = Book.all @user = current_user end
models/book.rb
class Book < ApplicationRecord belongs_to :user has_many :favorites, dependent: :destroy has_many :book_comments, dependent: :destroy def favorited_by?(user) favorites.where(user_id: user.id).exists? end validates :title, presence: true validates :body, presence: true, length: {maximum: 200} end
routes
Rails.application.routes.draw do get 'search/search' devise_for :users root 'homes#top' get 'home/about' => 'homes#about' get "users/show" => "users#show" get '/users' => "users#index" get "users/:id" => "users#show", as: :mypage get 'search' => "search#search" resources :users,only: [:show,:index,:edit,:update] do resources :relationships, only: [:create, :destroy] get :followings, on: :member get :followers, on: :member end resources :books do resource :favorites, only: [:create, :destroy] resources :book_comments, only: [:create, :destroy] end end
application.js
// This is a manifest file that'll be compiled into application.js, which will include all the files // listed below. // // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's // vendor/assets/javascripts directory can be referenced here using a relative path. // // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. JavaScript code in this file should be added after the last require_* statement. // // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require jquery3 //= require popper //= require bootstrap-sprockets //= require jquery //= require rails-ujs //= require activestorage //= require turbolinks //= require_tree .
試したこと
ここに問題に対して試したことを記載してください。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
どうぞ宜しくお願い致します。
あなたの回答
tips
プレビュー