🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby on Rails

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

Ajax

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

Q&A

1回答

1327閲覧

RailsでAjaxの非同期通信がうまくいきません

yuki1221

総合スコア6

Ruby on Rails

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

Ajax

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

0グッド

1クリップ

投稿2019/09/10 07:32

前提・実現したいこと

閲覧ありがとうございます。
三ヶ月目の初学者のため、文章など稚拙な部分はご容赦いただければと思います。

Ruby on rails で写真投稿型のアプリを作っています。
モデルはPost,User,Likeの3つです。

投稿の詳細画面(posts/show.html.erb)にいいねボタンを設置し、ajaxで「イイネ」⇄「イイネを取り消す」にしたいのですがうまくいきません。
厳密にはデータは送られているがそのビューで反映してくれない状態です。
(投稿詳細ページ → 「イイネ」ボタンを押す → topに戻る → 再び投稿詳細ページへ → 「イイネを取り消す」(イイネ数1)となっていたので、データは送られています。)

下記ソースコードになります。

該当のソースコード

  • models/post.rb
class Post < ApplicationRecord mount_uploader :image, ImageUploader default_scope -> { order(created_at: :desc) } belongs_to :user has_many :likes has_many :liked_users, through: :likes, source: :user end
  • models/user.rb
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :posts, dependent: :destroy has_many :likes, dependent: :destroy has_many :liked_posts, through: :likes, source: :post def already_liked?(post) self.likes.exists?(post_id: post.id) end end
  • models.like.rb
class Like < ApplicationRecord belongs_to :post belongs_to :user validates_uniqueness_of :post_id, scope: :user_id end
  • likes_controller.rb
class LikesController < ApplicationController def create @like = current_user.likes.create(post_id: params[:post_id]) end def destroy @like = Like.find_by(post_id: params[:post_id], user_id: current_user.id) @like.destroy end end
  • posts_controller.rb

Ruby

1class PostsController < ApplicationController 2 3 def show 4 @post = Post.find(params[:id]) 5 end 6 7end
  • posts/show.html.erb

Ruby

1<div class="detail"> 2 <%= image_tag @post.image.url, :size =>'480x480' %> 3 <%= simple_format(@post.text) %> 4 <div id="likes_buttons_<%= @post.id %>"> 5 <%= render partial: 'likes/like', locals: { post: @post } %> 6 </div> 7 <div class="like_count"> 8 <%= @post.likes.count %> 9 </div> 10 <div class="liked_user"> 11 <li>イイネしたユーザー</li> 12 <% @post.liked_users.each do |user| %> 13 <li><%= user.nickname %></li> 14 <% end %> 15 </div> 16</div>
  • likes/_like.html.erb

Ruby

1<% if current_user.already_liked?(post) %> 2 <%= button_to 'イイネを取り消す', post_like_path(post), method: :delete, remote: true %> 3<% else %> 4 <%= button_to 'イイネ', post_likes_path(post), method: :post, remote: true %> 5<% end %>
  • likes/create.js.erb
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
  • likes/destroy.js.erb
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");

コードが多く申し訳ありません、、、

試したこと/補足

  • 恥ずかしながらajaxを完璧に理解できておらず、どの変数が何を指しているのか混乱しています。

_like.html.erbのpostを@postに変えてみたりしましたがなかなかうまく動きません。

  • ユーザーがalready_likedかどうかは判断できているようです。

データは送られているが、非同期で反映してくれない状態?(create.jsやdestroy.jsが原因のような気がします)

その他補足情報

OS : mac
環境 : cloud9
データベース : mysql
ruby バージョン : ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
rails バージョン : 5.2.3

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

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

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

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

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

guest

回答1

0

erb

1$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");

@postを使っているようですがその@postがコントローラで用意されていません。
逆に@likeはどこで使うために用意されたのでしょうか。

sample

rb

1def create 2 @post = Post.find(params[:post_id]) 3 current_user.likes.create!(post_id: @post.id) 4end 5 6def destroy 7 @post = Post.find(params[:post_id]) 8 current_user.likes.find_by(post_id: @post.id).destroy! 9end

投稿2019/09/10 07:45

編集2019/09/10 07:47
Mugheart

総合スコア2349

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

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

yuki1221

2019/09/10 08:19

早速の回答ありがとうございます。 確かにおっしゃる通り全く使わない変数を定義していました... 修正したところ「イイネを取り消す」→「イイネ」(destroy)は問題なく非同期で遷移するようになったのですが、 「イイネ」→「イイネを取り消す」(create)がやはり再読み込みしないと反映されません。 今自分でも色々修正してみてるのですが、 他に何か原因など考えられますでしょうか?
Mugheart

2019/09/10 08:25

ログに何かエラーなどは出てないですか? デバッグを仕込んでみるとかやれることはたくさんあります。
yuki1221

2019/09/12 10:39

返信遅れまして申し訳ありません。 createの直前とdestroyの直前にbinding.pryでparamsを取得してみました。 [2] pry(#<LikesController>)> params => <ActionController::Parameters {"authenticity_token"=>"1f2/KjE8dJb3MPGXEFoTaXQ0quNZgW3RZP+1RQsHzYNrT0Tx9koK15K+bL7OsfxgFxiv70HYmF/w85EYD6Y9Pw==", "controller"=>"likes", "action"=>"create", "post_id"=>"10"} permitted: false> [1] pry(#<LikesController>)> params => <ActionController::Parameters {"_method"=>"delete", "authenticity_token"=>"C2VtcC7qwLGYvdjfou6QyFM14pt9FAW1FvyGlBMe3jU6d5F74y77XQej2dl3hIpUskgAxhtSI3Q5pD6Qgooqdg==", "controller"=>"likes", "action"=>"destroy", "post_id"=>"10", "id"=>"10"} permitted: false> permitted: falseとなっているのが原因でしょうか... ストロングパラメーターなどで取得しようと試みましたが、うまくいきません。 お手数おかけします...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問