🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails 6

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

Q&A

解決済

2回答

5752閲覧

高評価できる機能を作りたいのにundefined method `id' for nil:NilClassになってしまう。

kawasaki4563

総合スコア32

Ruby on Rails 6

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

0グッド

0クリップ

投稿2021/03/25 09:55

編集2021/03/26 11:57

自分のポートフォリオのアプリケーションに投稿に対して高評価できる機能を実装しようと思ったのですが、投稿が成功して投稿一覧ページに遷移するときにmodelの部分でエラーになってしまいます
ユーザー管理はdeviseを使っています。
参照させていただいた記事はこちらの記事です

Rails いいね機能のミニアプリを作ろう
エラー画面に出てきているコードは、
こちらの部分です
user.rbの部分のコードです

def already_liked?(post) self.likes.exists?(post_id: post.id) end

エラー文は以下の通りです

NoMethodError in Posts#index undefined method `id' for nil:NilClass

#問題のソースコードです

評価機能に関するコントローラー

class LikesController < ApplicationController def create @like = current_user.Likes.create(post_id: params[:post_id]) redirect_back(fallback_location: root_path) end def destroy @like = Like.find_by(post_id: params[:post_id], user_id: current_user.id) @like.destroy redirect_back(fallback_location: root_path) end end

投稿に関するコントローラー

class PostsController < ApplicationController before_action :authenticate_user!, only: [:new, :update, :create, :edit, :update, :destroy] before_action :find_post, only: [:edit, :update, :show, :destroy] def index @posts = Post.all @like = Like.new end def new @post = Post.new @like = Like.new end def show end def create @post = current_user @post = Post.create(post_params) if @post.save redirect_to root_path,notice:'投稿に成功しました' else redirect_to new_post_path,notice:'投稿に失敗しました' end end def edit end def update @post.update(post_params) end def destroy if @post.destroy redirect_to root_path,alert: '投稿を削除しました' else redirect_to root_path end end private def post_params params.require(:post).permit(:content, {images: []}).merge(user_id: current_user.id) end def find_post @post = Post.find(params[:id]) end def force_redirect_unless_my_post return redirect_to root_path,alert:'権限がありません'if @post.user != current_user end end

##ここからは評価機能に関するモデルです

class Like < ApplicationRecord belongs_to :user belongs_to :post validates_uniqueness_of :post_id, scope: :user_id end

以下は投稿に関すモデルです

class Post < ApplicationRecord has_many_attached :images belongs_to :user has_many :likes has_many :liked_users, through: :likes, source: :user validates :content, presence: true end

ユーザーに関するモデルです

class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_one_attached :image has_many :comments has_many :posts has_many :likes, dependent: :destroy has_many :liked_posts, through: :likes, source: :post def already_liked?(post) self.likes.exists?(post_id: post.id) end with_options presence: true do validates :name validates :mania_histry validates :enjoy_point validates :email validates :password, length: { minimum: 6 } end end

##ここからは評価機能をつけたビューです

<div class="content-wrapper"> <div class="content-block"> <% @posts.each do |post| %> <div class="content"> <div class="user-about"> <div class="image"> <% if post.user.image.attached? %> <%= image_tag post.user.image %> <% else %> <%= image_tag no.user.png %> <% end %> </div> <div class="profile"> <div class="name-history"> <div class="name"> <%= post.user.name %> </div> <div class="mania-histry"> <%= "学習歴:#{post.user.mania_histry}年" %> </div> </div> <div class="enjoy-point"> <%= "楽しいポイント#{post.user.enjoy_point}"%> </div> </div> </div> <div class="text"> <p><%= post.content %></p> </div> <% if post.images.attached? %> <% post.images.each do |image| %> <div class = 'images'> <%= image_tag image %> </div> <% end %> <% end %> <div class="action-menu"> <div class="like"> <h3>いいね件数: <%= post.likes.count %></h3> <div class = 'like-button'> <% if current_user.already_liked?(@post) %> <%= button_to 'いいねを取り消す', post_like_path(@post), method: :delete %> <% else %> <%= button_to 'いいね', post_likes_path(@post) %> <% end %> </div> </div> <div class="comment"> </div> </div> </div> <% end %> </div> <div class="sidebar"> <div class="box"> </div> <div class="box"> </div> </div> </div>

試したこと

ビューの部分に

<div class="like"> <h3>いいね件数: <%= post.likes.count %></h3> <div class = 'like-button'> <% if current_user.already_liked?(@post) %> <%= button_to 'いいねを取り消す', post_like_path(@post), method: :delete %> <% else %> <%= button_to 'いいね', post_likes_path(@post) %> <% end %> </div>

こちらの部分を

<div class="like"> <h3>いいね件数: <%= post.likes.count %></h3> <div class = 'like-button'>         <%if @post.present?%> <% if current_user.already_liked?(@post) %> <%= button_to 'いいねを取り消す', post_like_path(@post), method: :delete %> <% else %> <%= button_to 'いいね', post_likes_path(@post) %> <% end %> <% end %> </div>

として、postの部分の情報をとってこれるようにしようと思ったのですが、そしたらボタンそのものが表示されなくなってしまいました。
ですのでそれを消したあとに、パスの部分の(@post)の部分を消してみたところ、投稿は表示されたのですが、いいねボタン自体は機能していなかったです。
ですので、やっぱりpost_id :post.idの部分が機能していないあるいは、postのidをどこかで撮ってこれていないからではないかと考えています。

回答者様にアドバイスを頂いたので、

<%= button_to 'いいねを取り消す', post_like_path(post), method: :delete %> <% else %> <%= button_to 'いいね', post_likes_path(post) %> <% end %>

に変えてみたのですがやはり同じエラーでした。

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

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

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

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

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

guest

回答2

0

自己解決

解決しました。
方法としては、user.rbの部分の記述を

def liked_by?(post_id) likes.where(post_id: post_id).exists? end

に変更したあとに

ビューの部分を

<% if user_signed_in? %> <div class="like"> <h3>いいね件数: <%= post.likes.count %></h3> <div class = 'like-button'> <% if current_user.liked_by?(post.id) %> <td><%= link_to 'いいねを外す', destroy_like_path(post), class: "like-link", method: :DELETE %></td> <i class="fa fa-heart unlike-btn"></i> <% else %> <td><%= link_to 'いいね', create_like_path(post), class: "like-link", method: :create %></td> <i class="fa fa-heart like-btn"></i> <% end %>

に変更したら直しました。
ありがとうございました。
参考にしたのは以下の記事です
【Rails】いいね機能完全版!同期いいね、いいね数の表示、非同期いいね、アイコン表示、それぞれの実装方法についてまとめて解説

投稿2021/03/28 00:59

kawasaki4563

総合スコア32

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

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

0

<%= button_to 'いいねを取り消す', post_like_path(@post), method: :delete %> <% else %> <%= button_to 'いいね', post_likes_path(@post) %>

これらの @post を post に

投稿2021/03/25 14:13

winterboum

総合スコア23567

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

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

kawasaki4563

2021/03/26 01:24

回答ありがとうございます。 winterboumさんのアドバイス道理に@postとなっていたところをpostに変えてみたところ同じエラーになってしまいました。 解決はできませんでした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問