Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

rails 非同期いいねを実装したいのですが、エラーが出てしまいます。 初心者です。

解決したいこと

railsでTwitterのようなサイトを作っています。
インデックスページのいいね機能を非同期通信に変更しようとしている際にエラーが起きてしまい、その解決をしたいです。

ruby 3.1.2
Rails 7.0.3
deviseなし

エラー

.error
NoMethodError in PostsController#show
undefined method `user' for nil:NilClass

@user = @post.user

現在のコード

route.rb
省略
  get "likes/:post_id/indexcreate" => "likes#indexcreate", as: :create_likes 
  get "likes/:post_id/indexdestroy" => "likes#indexdestroy", as: :destroy_likes
省略
  get "posts/:id" => "posts#show", as: :post
posts/index.html.erb
    <% @posts.each do |post| %>
      <div class="posts-index-item">
        <div class="post-left">
省略
          <td id="posts_likes_<%= post.id %>">
          <%= render "posts/likes", post: post %>
省略
posts/create.js.erb/ posts/destroy.js.erb
$('#posts_likes<%= @post.id %>').html("<%= j(render "posts/likes", post: @post) %>");
likes_controller.rb
省略
    def indexcreate
      @like = Like.new(user_id: @current_user.id, post_id: params[:post_id])
      @like.save
    end
  
    def indexdestroy
      @like = Like.find_by(user_id: @current_user.id, post_id: params[:post_id])
      @like.destroy
    end
posts/_likes.html.erb
<% if @current_user && Like.find_by(user_id: @current_user.id, post_id: post.id) %>
<%= link_to("destroy_likes_path(user_id: current_user.id, post_id: params[:post_id])", {method: "post", remote: "true"}) do %>
  <span class="fa fa-heart liked-btn"></span>
<% end %>
<% else %>
<%= link_to("create_likes_path(user_id: current_user.id, post_id: params[:post_id])", {method: "post", remote: "true"}) do %>
  <span class="fa fa-heart unliked-btn"></span>
<% end %>
<% end %>
<%= @post_like_count[post.id] %>

最後まで読んでいただきありがとうございます。
教えて頂けると幸いです。
よろしくお願いいたします。

0

1Answer

エラーメッセージに NoMethodError in PostsController#show と書いてあるのに PostsController 関係のコードを質問に含めていないということは、エラーの読み方をまだ理解されていないとお見受けします。まずエラーについて説明します。

NoMethodError in PostsController#show
undefined method `user' for nil:NilClass

@user = @post.user

1行目は、 PostsControllershow メソッドの中(またはそこで render されるテンプレートファイルの中)で NoMethodError が起きていることを表します。余談ですが、Ruby ではインスタンスメソッドの頭に # をつけて #show と表記することが一般的です。

2行目は NoMethodError が起きた理由です。 nil に対して user メソッドを呼び出そうとして失敗したことを表します。

それ以降の行は、エラーが出たコードです。 エラーの理由を踏まえると、 @post が nil になっているだろうと分かります。

nil になる理由は @post に代入する部分にあります。おそらく @post = Post.find_by(...) のようなコードがあると思いますが、そこで目的の Post が見つかっていないことが原因です。

コードを見直し、分からなければ原因と思われるコードを追記して質問し直してください。

3Like

Comments

  1. @NetaNeta0620

    Questioner

    返信ありがとうございます。
    下記コードがpost_controllerのshowメソッドになります。

    def show
    @post = Post.find_by(id: params[:id])
    @user = @post.user
    @likes = Like.where(user_id: @user.id)
    @likes_count = Like.where(post_id: @post.id).count
    @comments_count = Comment.where(post_id: @post.id).count
    @comment = Comment.new
    @comments = @post.comments.includes(:user)
    @post_detail = Post.find(params[:id])
    if @current_user.present?
    unless ViewCount.find_by(user_id: @current_user.id, post_id: @post_detail.id)
    @current_user.view_counts.create(post_id: @post_detail.id)
    end
    end
    @post_like_count = Like.group(:post_id).count
    @post_comments_count = Comment.group(:post_id).count
    end

    何かわかると良いのですが

    原因を教えて頂けると幸いです

  2. 回答で述べたように、 @user = @post.user@post が nil なのですから、その上の行の @post = Post.find_by(id: params[:id]) が原因です。
    Post.find_by は Post が見つからなかったときに nil を返します。
    Post が見つからないのは、指定した id の Post が存在しないか、 id が nil のときです。

    エラーが出たとき、 Post へのリンクをクリックしたのではありませんか?
    そのリンクの URL に含まれる id が間違っていると思われます。
    リンクを生成するビューのコードを見直してください。

Your answer might help someone💌