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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

1731閲覧

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

W.K

総合スコア13

Ruby on Rails 5

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

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

1クリップ

投稿2019/02/12 12:30

前提・実現したいこと

現在画像投稿機能のついた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を使用しています。

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

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

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

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

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

guest

回答2

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 }) %>");

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

投稿2019/02/13 02:03

W.K

総合スコア13

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

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

0

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

投稿2019/02/13 00:28

Kta-M

総合スコア456

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

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

W.K

2019/02/13 01:39

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

2019/02/13 01:43

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

2019/02/13 01:50

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問