質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

89.93%

Rails5でAjaxを利用したいいね機能をつけたい

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 475

W.K

score 7

前提・実現したいこと

現在画像投稿機能のついたSNSを作っており、投稿詳細画面で一つ一つの投稿に対していいね機能をつけようと思っています。具体的には、ajaxの非同期通信を使って、ユーザーがいいねを押すとハートの色が変わり、もう一度押すと色が戻るようにしたいです。
下記のサイトを参考にしました。
リンク内容

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

いいねを押すとcreateアクションによってfavoritesテーブルにレコードが追加されますが、サイト上で手動でリロードを行わない限りハートの色は変わらない状態です。いいね機能自体はリロードを行えばしっかり動くのですが、エラーは出ないのですが、create.js.erb(またはdestroy.js.erb)がうまく作動せず困っています。

以下いいねボタンを押したときのターミナルです。

Started POST "/posts/5/favorites" for 127.0.0.1 at 2019-02-12 21:18:21 +0900
Processing by FavoritesController#create as JS
  Parameters: {"authenticity_token"=>"bU4W35RhgQlQGdP/ganSnkbyvDbH6xlwBOvo3dnCI8Q//BP14aJbfZXNNGVZXLamrCtMcz6s7DLgfdU8yxEoIA==", "post_id"=>"5"}
  User Load (2.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ?  [["LIMIT", 1]]
  ↳ app/controllers/application_controller.rb:13
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 3], ["LIMIT", 1]]
  ↳ /Users/kw/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
  Post Load (0.2ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = ? ORDER BY "posts"."created_at" DESC LIMIT ?  [["id", 5], ["LIMIT", 1]]
  ↳ app/controllers/favorites_controller.rb:27
  Favorite Load (0.2ms)  SELECT  "favorites".* FROM "favorites" WHERE "favorites"."user_id" = ? AND "favorites"."post_id" = ? LIMIT ?  [["user_id", 3], ["post_id", 5], ["LIMIT", 1]]
  ↳ app/controllers/favorites_controller.rb:6
  Post Load (0.3ms)  SELECT  "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ?  [["id", 5], ["LIMIT", 1]]
  ↳ app/controllers/favorites_controller.rb:11
  Rendering favorites/create.js.erb
  Favorite Load (0.2ms)  SELECT  "favorites".* FROM "favorites" WHERE "favorites"."post_id" = ? AND "favorites"."user_id" = ? LIMIT ?  [["post_id", 5], ["user_id", 3], ["LIMIT", 1]]
  ↳ app/models/post.rb:10
  Favorite Load (0.2ms)  SELECT "favorites".* FROM "favorites" WHERE "favorites"."post_id" = ?  [["post_id", 5]]
  ↳ app/views/favorites/_favorite_form.html.erb:3
  Rendered favorites/_favorite_form.html.erb (4.4ms)
  Rendered favorites/create.js.erb (31.0ms)
Completed 200 OK in 106ms (Views: 66.8ms | ActiveRecord: 5.2ms)

該当のコード

post.rb

class Post < ApplicationRecord
    belongs_to :user
    has_many :favorites, dependent: :destroy
    has_many :users, through: :favorites

    def like_user(user_id)
        favorites.find_by(user_id: user_id)
    end

end


favorites_controller.rb

class FavoritesController < ApplicationController
    before_action :authenticate_user!
    before_action :set_post

    def create
        @favorite = Favorite.find_or_create_by(
            user_id: current_user.id,
            post_id: params[:post_id]
            )
        @favorites = Favorite.where(post_id: params[:post_id])
        @post.reload
    end

    def destroy
        favorite = Favorite.find_by(
            user_id: current_user.id,
            post_id: params[:post_id]
        )
        favorite.destroy
        @favorites = Favorite.where(post_id: params[:post_id])
        @post.reload
    end

    private

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

end


favorite.rb

class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :post, counter_cache: :likes_count
end


posts/show.html.erb

:
:省略
:
<div id="likes_buttons_<%= @post.id %>" >
    <%= render partial: 'favorites/favorite_form', locals: { post: @post } %>
</div>


favorites/_favorite_form.html.erb

<% if user_signed_in? %>
  <% unless @post.like_user(current_user.id).blank? %>
    <%= button_to post_favorite_path(post_id: @post.id, id: @post.favorites[0].id), 
              method: :delete, id: "like-button", remote: true do %>
        <span class="fa fa-heart like-btn-unlike"></span>
      <span>
        <%= @post.likes_count %>
      </span>
    <% end %>
  <% else %>
    <%= button_to post_favorites_path(@post), method: :post, id: "like-button", remote: true do %>
        <span class="fa fa-heart like-btn"></span>
      <span>
        <%= @post.likes_count %>
      </span>
    <% end %>
  <% end %>
<% else %>
    <span class="fa fa-heart like-btn"></span>
    <span>
      <%= post.likes_count %>
    </span>
<% end %>


favorites/create.js.erb

$("#like-buttons_<%= @post.id %>").html("<%= j(render partial: 'favorite_form', locals: { posts: @posts }) %>");


favorites/destroy.js.erb

$("#like-buttons_<%= @post.id %>").html("<%= j(render partial: 'favorite_form', locals: { posts: @posts }) %>");

試したこと

teratailで似た質問を参考にして見たのですがうまくいきませんでした。
リンク内容
リンク内容

補足情報(FW/ツールのバージョンなど)

Ruby 2.5.0
Rails 5.2.2
ログイン機構はdeviseを使用しています。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

create.js.erb と destroy.js.erb において

$("#like-buttons_<%= @post.id %>").html("<%= j(render partial: 'favorite_form', locals: { posts: @posts }) %>");


"#like-buttons_<%= @post.id %>"と指定していたのにもかかわらず

favorites/_favorite_form.html.erbで

<% if user_signed_in? %>
  <% unless @post.like_user(current_user.id).blank? %>
    <%= button_to post_favorite_path(post_id: @post.id, id: @post.favorites[0].id), 
              method: :delete, id: "like-button", remote: true do %>
        <span class="fa fa-heart like-btn-unlike"></span>
      <span>
        <%= @post.likes_count %>
      </span>
    <% end %>
  <% else %>
    <%= button_to post_favorites_path(@post), method: :post, id: "like-button", remote: true do %>
        <span class="fa fa-heart like-btn"></span>
      <span>
   :
   :


id: "like-button" となっており

posts/show.html.erbでも

<div id="likes_buttons_<%= @post.id %>" >
    <%= render partial: 'favorites/favorite_form', locals: { post: @post } %>
</div>


id="likes_buttons_<%= @post.id %>"となっていたことが原因でした。

以下動いたコードです。
posts/show.html.erb

   :
   :
<div id="likes-buttons-<%= @post.id %>" >
    <%= render partial: 'favorites/favorite_form', locals: { post: @post, favorites: @favorites, favorite: @favorite } %>
</div>


favorites/_favorite_form.html.erb

<% if user_signed_in? %>
  <% unless @post.like_user(current_user.id).blank? %>
    <%= button_to post_favorite_path(post_id: @post.id,id: @post.favorites[0].id), 
              id: "likes-button-#{@post.id}", method: :delete, remote: true do %>
        <span class="fa fa-heart like-btn-unlike"></span>
      <span>
        <%= @post.likes_count %>
      </span>
    <% end %>
  <% else %>
    <%= button_to post_favorites_path(@post), id: "likes-button-#{@post.id}", 
              method: :post, remote: true do %>
        <span class="fa fa-heart like-btn"></span>
      <span>
    :
    :


create.js.erb と destroy.js.erb

$("#likes-button-<%= @post.id %>").html("<%= j(render 'favorite_form', locals: { post: @post }) %>");

とすべて統一しました。
すごく時間がかかりましたが、回答してくれた方々、他の質問者の方のおかげで解決できました。ありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

create.js.erb/destroy.js.erbのlocalsには、
postsではなくpostを渡さないといけないのではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/13 10:39

    回答ありがとうございます!
    postsからpostに変更し、また他の似たような境遇の方のコードを参考にfavorite: @favorite, favorites: @favoritesも付け足したのですが何も変化が見られませんでした。

    キャンセル

  • 2019/02/13 10:43

    favorites/_favorite_form.html.erbの中では、@favoriteも@favoritesも使っていないのでそれは不要だと思います。
    書き方が悪かったかもしれないので念のため確認ですが、{ post: @posts }になっていませんか?もしそうなっていれば、{ post: @post }にしてみてください。

    キャンセル

  • 2019/02/13 10:50

    たった今解決しました!(後ほど上に↑載せます)
    回答していただきありがとうございました!
    またおっしゃる通り、@favoriteは@favoritesはなくても動きました。

    キャンセル

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

  • ただいまの回答率 89.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る