実現したいこと
再度、Railsの勉強を始めたいと思い、いいね機能を作成してみたところ、「いいね」を押すと「NoMethodError in FavoritesController#destroy」というエラーが出てきてしまい問題解決が困難なため、こちらのエラーの対処法のご教授をお願い致します。
前提
いいね機能ですが、一度目はいいねを押しても問題ないのですが、2度目(「いいね」を押したものとは別の「いいね」です)を押すと下記エラーが起きてしまいます。
また、1度目の「いいね」を消して再度、別のいいねを押すと問題なくいいねを押せました。
発生している問題・エラーメッセージ
エラーメッセージ NoMethodError in FavoritesController#destroy undefined method `destroy' for nil:NilClass @blog = Blog.find(params[:blog_id]) favorite = current_user.favorites.find_by(blog_id: @blog.id) favorite.destroy #ここです redirect_to blog_path(@blog) end Rails.root: /app app/controllers/favorites_controller.rb:14:in `destroy' Request Parameters: {"_method"=>"delete", "blog_id"=>"3"} Toggle session dump Toggle env dump Response Headers: None (byebug使用時) onsen-app-1 | 9: onsen-app-1 | 10: def destroy onsen-app-1 | 11: @blog = Blog.find(params[:blog_id]) onsen-app-1 | 12: favorite = current_user.favorites.find_by(blog_id: @blog.id) onsen-app-1 | 13: byebug onsen-app-1 | => 14: favorite.destroy onsen-app-1 | 15: redirect_to blog_path(@blog) onsen-app-1 | 16: end onsen-app-1 | 17: onsen-app-1 | 18: end
該当のソースコード
routes.rb resources :blogs do resource :favorites, only: [:create, :destroy] collection do get 'see' => 'blogs#see' get 'look' => 'blogs#look' get 'saw' => 'blogs#saw' get 'watch' => 'blogs#watch' get 'seeing' => 'blogs#seeing' get 'looking' => 'blogs#looking' get 'check' => "blogs#check" get "try" => "blogs#try" get "gaze" => "blogs#gaze" get "info" => "blogs#info" get "precautions" => "blogs#precautions" end end
models/favorite.rb class Favorite < ApplicationRecord belongs_to :user belongs_to :blog end
models/user.rb class User < ApplicationRecord has_many :favorites, dependent: :destroy end
models/blog.rb class Blog < ApplicationRecord has_many :favorites, dependent: :destroy def favorited_by?(user) Favorite.where(user_id: user.id).exists? end end
controllers/favorites_controller.rb class FavoritesController < ApplicationController def create @blog = Blog.find(params[:blog_id]) favorite = current_user.favorites.new(blog_id: @blog.id) favorite.save redirect_to blog_path(@blog) end def destroy @blog = Blog.find(params[:blog_id]) favorite = current_user.favorites.find_by(blog_id: @blog.id) favorite.destroy redirect_to blog_path(@blog) end end
views/blogs/_blogs.html.erb <ul class="card-footer"> <%= @blog.user.name %> <% if @blog.present? %> <% if @blog.favorited_by?(current_user) %> <li class="card-footer"> <%= link_to blog_favorites_path(@blog), method: :delete do %> <i class="fa fa-heart" aria-hidden="true" style="color: red;"></i> <%= @blog.favorites.count %> <% end %> </li> <% else %> <li> <%= link_to blog_favorites_path(@blog), method: :post do %> <i class="fa fa-heart" aria-hidden="true" style="color: red;"></i> <%= @blog.favorites.count %> <% end %> </li> <% end %> <% end %> </ul>
viwes/favorites/favorite.js.erb $("<%= @id_name %>").html('<%= escape_javascript(render("favorites/favorite", blog: @blog )) %>'); viwes/favorites/not_favorite.js.erb $("<%= @id_name %>").html('<%= escape_javascript(render("favorites/favorite", blog: @blog )) %>');
試したこと
再度勉強し始めたいと思い、下記参考サイトを調べたところ、やはり知識不足という指摘があったので現在進行形で復習をしております。
参考サイト
https://ichigick.com/undefined-method-for-nil/
知識不足内容
Ruby
変数
変数の定義の仕方
インスタンス
インスタンスメソッド
インスタンスメソッドに対するメソッドの呼び出し方
メソッドの引数
メソッドの戻り地
ブロック構文とブロック引数(特に each メソッドによるループ)
Ruby on Rails
ルーター(routes.rb) の定義によるコントローラ・アクションの呼び出しルール
コントローラからビューを呼び出すルールと、インスタンス変数による値の共有
ビューからビューを呼び出す(パーシャル)ときに変数を指定する方法
補足情報(FW/ツールのバージョンなど)
開発環境
- VSCode
- Docker/Docker-compose
フロントエンド
- HTML/CSS
- JavaScript
バックエンド
- Ruby 2.7.3
- Ruby on Rails 6.1.3.2
以前、勉強用に使用していたものと同じものを使用しているため、若干古いバージョンかとは思いますがよろしくお願い致します。
0 コメント