@yude3939 (雄大 田中)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

非同期でいいねができない状態です。

Ruby on Railsで非同期通信のいいね機能の実装に取り組んでいますが
エラーが出て非同期でいいねができない状態です。
同期通信ではいいねは可能です。

解決方法を教えて下さい。

発生している問題・エラー

ActionView::Template::Error (undefined method `id' for nil:NilClass):
$("#like_heart_<%= @post.id %>").html("<%= j(render 'likes/like', locals: {post: @post}) %>");

app/views/likes/create.js.erb:1

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
ここが間違っているかと仮定して変更したりしましたが
実装にまでたどりつきません。
お時間ある方お願いします。

likes_controller.rb
class LikesController < ApplicationController
  def create
    post = Post.find(params[:post_id])
    @like = Like.create(user_id: current_user.id, post_id: post.id)
  end

  def destroy
    post = Post.find(params[:post_id])
    @like = Like.find_by(user_id: current_user.id, post_id: post.id)
    @like.destroy
  end
end
show.html.erb
<main class="main">
<div class= "null">
</div>
<div id="map"></div>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=<%=ENV['GOOGLE_MAP_KEY']%>&callback=initMap&v=weekly"
      async
    ></script>
    <script>
    let map;

function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: <%= @post.latitude %>, lng: <%= @post.longitude %>},
    zoom: 15,
  });
  var marker = new google.maps.Marker({
      position: { lat: <%= @post.latitude %>, lng: <%= @post.longitude %>},
      map: map,
      title: "<%= @post.address %>"
    });
}
    </script>

  <div class="inner">
    <div class="post__wrapper">
      <div class="post_show_image">
        <%= image_tag @post.image.variant(resize: '500x500'), class: "post_show_image" %>
      </div>
      <div class="post__body">
        <div class="post_address">
          <%= @post.address %>
          <div id="like_heart_<%= @post.likes %>">
            <%= render partial: "likes/like", locals: {  post: @post, likes: @likes } %>
          </div>
        </div>
        <div class="post_spring_quality">
          <div class="detail__message">
            泉質:
            <%= @post.spring_quality %>
          </div>
        </div>
        <div class="post_description">
          <div class="detail_description">
            <%= @post.description %>
          </div>
        </div>
        <div class="post_bottom">
        <div class="post_name">
          投稿者:
          <%= link_to @post.user.name, user_path(@post.user), class: :post__user %>
          </div>
          <div class="post_comment">
          "コメント"
          </div>
        </div>
        <% if user_signed_in? %>
          <%= form_with model: [@post, @comment], local: true do |f|%>
            <div class="input">
              <%= f.text_field :content, id:"comment_content" %>
            </div>
            <div class="actions-comment">
              <%= f.submit "送信する", class: :comment__btn  %>
            </div>
          <% end %>
        <% end %>
        <div class="comments_lists">
          <% @comments.each do |comment| %>
            <div class="comments_list">
              <%= link_to "#{comment.user.name}:", user_path(comment.user), class: :comment_user %>
              <%= comment.content%>
            </div>
            <% if user_signed_in? && current_user.id == comment.user_id %>
            <%= link_to "削除", post_comment_path(comment.post.id, comment.id), method: :delete,class: :comment_delete %>
            <% end %> 
          <% end %>
        </div>
  
      <% if user_signed_in? && current_user.id == @post.user_id %>
         <div class="post__manage"> 
           <%= link_to "編集する", edit_post_path(@post.id), method: :get,class: :post__btn %> 
           <%= link_to "削除する", post_path(@post.id), method: :delete,class: :post__btn %> 
         </div> 
       <% end %> 
    </div>
  </div>
</main>
_like.html.erb
<div class="like-hearts">
<%if user_signed_in? %>
    <% if Like.find_by(user_id: current_user.id, post_id: @post.id) %>
        <%= link_to  post_like_path(@post,@post.likes), class: "like-link", method: :delete, remote: true do %>
          <i class="fas fa-heart unlike-btn"></i>
        <% end %>
        <div class="count"><%= @post.likes.count %></div>
    <% else %>
        <%= link_to post_likes_path(@post,@post.likes), class: "like-link", method: :post, remote: true do %>
          <i class="far fa-heart like-btn"></i>
        <% end %>
        <div class="count"><%= @post.likes.count %></div>
    <% end %>
  <% else %>
      <i class="fas fa-grin-squint-tears unlike-btn"></i><p class="count"><%= post.likes.count %></p>
<% end %>
</div>
create.js.erb
$("#like_heart_<%= @post.id %>").html("<%= j(render 'likes/like', locals: {post: @post}) %>");
0 likes

1Answer

エラーの読み方から解説します。

ActionView::Template::Error (undefined method `id' for nil:NilClass):

これは、 値 nil に対してid メソッドを呼び出したが、 nil はそんな名前のメソッドを持っていない(未定義、 undefined)ので呼び出せないという意味です。エラーが出ているコードを見てみると、

create.js.erb
$("#like_heart_<%= @post.id %>").html("<%= j(render 'likes/like', locals: {post: @post}) %>");

id を呼んでいる箇所は @post.id だけです。よって @postnil だと見当がつきます。 Ruby のインスタンス変数(@ で始まる変数)は何か代入する前に参照すると nil になるので、 @postnil を代入してあるか、または何も代入していないかの2通りが考えられます。

ここで、 create.js.erb は LikesController create メソッドでレンダリングされます。そこでは @post に何も代入していないので nil になることが分かります。よって create メソッドの

post = Post.find(params[:post_id])

@post = Post.find(params[:post_id])

に変えれば直るはずです。

0Like

Comments

  1. @yude3939

    Questioner

    お答えしていただきありがとうございます。

    上記のやり方をした場合、いいねが押せない状況になりまして以下のエラーが出たしまいました。

    NameError (undefined local variable or method `post' for #<LikesController:0x00007fe513096460>
    Did you mean? @post):

    app/controllers/likes_controller.rb:4:in `create'
  2. 変えた行の1行下で post.id を使っているのを @post.id に直してください。
  3. @yude3939

    Questioner

    できました。
    お忙しい中、ありがとうございました。

Your answer might help someone💌