86421


※他のサイトでも同様の質問を行っています。解決後はそれぞれ更新致します。よろしくお願いします。  
<https://teratail.com/questions/av2uvajgpeg8dy>

### 前提・実現したいこと

投稿された質問(post)に対して回答したコメント(comment)に非同期通信でいいね(good)を押す機能を実装したいです。

### 発生している問題・エラーメッセージ

設置したいいねリンクでcreateアクションが実行されません。  
ビューは表示されており、検証ツールで以下のエラーが生じています。  
画面のハートを押すとこのような挙動になります。

rails-ujs.js:216 POST http://localhost:3000/posts/1/comments/8/goods 404 (Not
Found)  
![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-02-17/1dd2de2a-d961-4209-8fb2-e94f094d1df3.png)

### 自分で調べたことや試したこと

質問に対してのいいねは以下記事を参考にし、実行できました。  
<https://qiita.com/max_3252/items/ca8f623563e26b6a8630>

次はそのコードを流用する形でコメントへのいいねを実装しようとしましたが、このようなエラーが生じています。

404 not foundについて調べたところ、リンク切れやリダイレクトの設定ミスとありました。  
リンク切れは無いとして、リダイレクトの設定ミスかと模索しました。

エラー内容にて、http://localhost:3000/posts/1/comments/8/goods とあり、  
post_idやcomment_idの取得、methodの指定も行なっているので問題ないのでは...と思い、原因を掴めていません。

### 使っているツールのバージョンなど補足情報

ruby: 3.0.2  
rails: 6.0.4  
jquery-rails: 4.4.0

* * *

### 該当のソースコード

ルーティング

[code]

    routes.rb
    
    Rails.application.routes.draw do
    （省略）
      resources :posts do
        resources :favorites, only: %i[create destroy]
        resources :comments, only: %i[create destroy] do
          resources :goods, only: %i[create destroy]
        end
      end
    end
    
[/code]

ビュー関連

[code]

    app/views/goods/create.js.erb
    
    $('#goods_buttons<%= @comment.id %>').html("<%= j(render partial: 'goods/good', locals: {post: @post, comment: @comment}) %>");
    
[/code]

[code]

    app/views/goods/destroy.js.erb
    
    $('#goods_buttons<%= @comment.id %>').html("<%= j(render partial: 'goods/good', locals: {post: @post, comment: @comment}) %>");
    
[/code]

[code]

    app/views/goods/_good.html.erb
    
    <% unless @comment.good_user(@current_user.id).blank? %>
        <%= link_to post_comment_good_path(post_id: @post.id, comment_id: comment.id), method: :delete, remote: true do %>
          <div class="vertical_good">
           <%= image_tag "icon_red_heart.png", size: '20x20' %>
          </div>
        <% end %>
      <% else %>
        <%= link_to post_comment_goods_path(@post, comment), method: :post, remote: true do %>
          <div class="vertical_good">
            <%= image_tag "icon_heart.png", size: '20x20' %>
          </div>
        <% end %>
      <% end %>
    
[/code]

[code]

    app/views/comments/_comment.html.erb
    
    <div class="p-comment__item">
      <p><%= simple_format(comment.comment) %></p>
      <div class="p-comment__bottomLine">
        <div id="goods_buttons<%= comment.id %>">
          <%= render partial: 'goods/good', locals: { post: @post, comment: comment } %>
        </div>
        <span><%= comment.created_at.to_s(:datetime_jp) %></span>
        <span><%= link_to '削除', post_comment_path(@post, comment), method: :delete, data: { confirm: '削除してよろしいですか？' } %></span>
      </div>
    </div>
    
[/code]

[code]

    app/views/posts/show.html.erb
    
    （一部省略）
    <div class="p-comment__list">
      <div class="p-comment_listTitle">コメント</div>
      <%= render @post.comments %>
    </div>
    
    <%= render partial: 'comments/form', locals: { comment: @comment } %>
    
[/code]

コントローラ

[code]

    goods_controller.rb
    
    class GoodsController < ApplicationController
      before_action :set_comment, only: %i[create destroy]
    
      def create
        @good = Good.create(user_id: current.user_id, post_id: @post.id, comment_id: @comment.id)
      end
    
      def destroy
        good = Good.find_by(user_id: current.user_id, comment_id: comment.id)
        good.destroy
      end
    
      private
    
      def set_comment
        @post = Post.find(params[:id])
        @comment = Comment.find(comment_id: @post.id)
      end
    end
    
[/code]

[code]

    comments_controller.rb
    
    class CommentsController < ApplicationController
      def create
        comment = Comment.new(comment_params)
        if comment.save
          flash[:notice] = 'コメントを投稿しました'
          redirect_to comment.post
        else
          flash[:comment] = comment
          flash[:error_messages] = comment.errors.full_messages
          redirect_back fallback_location: comment.post
        end
      end
    
      def destroy
        comment = Comment.find(params[:id])
        comment.delete
        redirect_to comment.post, flash: { notice: 'コメントが削除されました' }
      end
    
      private
    
      def comment_params
        params.require(:comment).permit(:post_id, :comment)
      end
    end
    
[/code]

[code]

    posts_controller.rb
    
    class PostsController < ApplicationController
      before_action :set_target_post, only: %i[show edit update destroy]
    
    （省略）
      
      def show
        @comment = Comment.new(post_id: @post.id)
      end
    
    （省略）
    
      private
    
    （省略）
    
      def set_target_post
        @post = Post.find(params[:id])
      end
    end
    
[/code]


CC BY-SA 4.0
2022-02-17T14:34:22.430
86419
2022-02-18T01:17:32.903
2022-02-18T01:17:32.903
3060
51475
question
ruby-on-rails ruby jquery ajax
Rails でいいねの create アクションが実行されない


`goods_controller.rb`にある、

[code]

    @comment = Comment.find(comment_id: @post.id)
    
[/code]

ですが、`find`メソッドは引数にIDを取ります。ハッシュを渡しても動作しません。  
<https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-
find>  
この際、`Comment`レコードが見つからないため、Railsは「リソースが見つからなかった」際に出すべき404のステータスコードを返します。

ここではコメントのIDがすでに分かっており（今ならば`8`）、それを使ってコメントの取得ができます。

[code]

    @comment = Comment.find(params[:comment_id])
    
[/code]

と、ここまで書いていて気づいたのですが、Postを取得している

[code]

    @post = Post.find(params[:id])
    
[/code]

も、

[code]

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

に変更したほうがよいかもしれません。Railsの`params`に渡ってくる`id`関係の値がどのようなキーで取得できるかは`resources`の書き方によって変わってくるためです。

なお、

> 404 not foundについて調べたところ、リンク切れやリダイレクトの設定ミスとありました。  
>  リンク切れは無いとして、リダイレクトの設定ミスかと模索しました。

というのは一般的な理解ではあるのですが、Railsはデータベースからレコードを発見できなかったときに404を返すのは覚えておいてください。


CC BY-SA 4.0
2022-02-17T16:35:31.963
86421
2022-02-17T16:35:31.963
442
86419
answer