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

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

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

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

Q&A

解決済

1回答

702閲覧

RailsでAjaxをちゃんと動かしたい

marutama_giant

総合スコア16

Ruby on Rails

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

0グッド

0クリップ

投稿2017/08/18 11:31

編集2017/08/20 08:50

Railsでrailsとjsを使ったお手軽「いいね♡機能」をみながら、「いいね♡機能」を実装しているのですが、[いいね!ボタン]を押したあとにリロードしなければ画面が変化しません。Ajaxでリロードなしで変更できるようにしたいのですが、Rails側でエラーが出ているのですが、解決できません。。

エラーメッセージ

Ruby

1 Rendered likes/_like.html.erb (270.1ms) 2 Rendered likes/create.js.erb (288.5ms) 3Completed 500 Internal Server Error in 381ms (ActiveRecord: 21.7ms) 4 5ActionView::Template::Error (undefined local variable or method `micropost' for #<#<Class:0x007f902c142940>:0x007f90284f6658>): 6 1: <% if logged_in? %> 7 2: <% if micropost.like_user(current_user.id) %> 8 3: <%= button_to micropost_like_path(micropost_id: micropost.id, id: 1), method: :delete, id: "like-button", remote: true do %> 9 4: <%= image_tag("hot.png", style: "width: 20px;") %> 10 5: <span>

###該当するソースコード

_like.html.erb

ruby

1<% if logged_in? %> 2 <% if micropost.like_user(current_user.id) %> 3 <%= button_to micropost_like_path(micropost_id: micropost.id, id: 1), method: :delete, id: "like-button", remote: true do %> 4 <%= image_tag("hot.png", style: "width: 20px;") %> 5 <span> 6 <%= micropost.likes_count %> 7 </span> 8 <% end %> 9 <% else %> 10 <%= button_to micropost_likes_path(micropost),id: "like-button", remote: true do %> 11 <%= image_tag("not.png", style: "width: 20px;") %> 12 <span> 13 <%= micropost.likes_count %> 14 </span> 15 <% end %> 16 <% end %> 17<% else %> 18 <%= image_tag("not.png") %> 19 <span> 20 <%= micropost.likes_count %> 21 </span> 22<% end %>

create.js.erb

Ruby

1$("#like-buttons").html("<%= j(render partial: 'like', locals: { microposts: @microposts, likes: @likes, like: @like}) %>")

destroy.js.erb

Ruby

1$("#like-buttons").html("<%= j(render partial: 'like', locals: { microposts: @microposts, likes: @likes }) %>");

likes_controller.rb

Ruby

1class LikesController < ApplicationController 2 def create 3 @like = Like.create(user_id: current_user.id, micropost_id: params[:micropost_id]) 4 @likes = Like.where(micropost_id: params[:micropost_id]) 5 @microposts = Micropost.all 6 end 7 8 def destroy 9 like = Like.find_by(user_id: current_user.id, micropost_id: params[:micropost_id]) 10 like.destroy 11 @likes = Like.where(micropost_id: params[:micropost_id]) 12 @microposts = Micropost.all 13 end 14end

すみませんがどうぞ宜しくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

参照先URLのすべてのソースを見たわけではないですが、エラーが発生している原因は、
_like.html.erbパーシャルにmicropost変数を渡していないからですね。
(現実装では、渡しているのは、micropostsだが、パーシャル内で利用しているのはmicropost)
そのため、DBに対する保存は完了しているが、Ajax処理がこけているという状況かと思います。

パーシャルに対する理解がわからなければ、
http://qiita.com/shizuma/items/1c655dadd2e04b3990a8
を見ておくとよいと思います。

ちなみに参照先のURLの実装にも同様のミスが見つかりました。その他にも、いくつか不可解な部分があります。完全にトレースした訳ないですが、おそらくこの投稿のまま実装しても動かないですね。
・views/likes/create.js.erbで$("#like-buttons")というhtml要素を書き換えているが、このlike-buttonsとは???命名からするとすべてのいいねボタンと見受けられるが、ajaxで再描画するのは一ついいねボタンだけで良いはず。
・partial内で利用しているのはtweetだが、渡しているのはtweets
・create, destroyともに@tweetsや@likes、@likeは不要なはず
といったところです。

micropostsを表示している一覧ページがありますよね?(そしてその中にいいねボタンがあると思うのですが)
もしよければ、そこのerbテンプレートを貼ってみてください。修正方針が伝えられるかも。

<以下追記>

_micropost.html.erbを以下のようにしてみてください。
likeパーシャルをなんでも良いのでタグで囲ってそこにIDを付与します

html

1<li id="<%= micropost.id %>"> 2<%= link_to gravatar_for(micropost.user, size: 50), micropost.user %> 3<span class="user"><%= link_to micropost.user.name, micropost.user %></span> 4<span class="content"><%= micropost.content %></span><br /> 5<span class="rate rate-<%= micropost.rate %>"></span><br /> 6<span class="type"><%= micropost.type %></span><br /> 7<span class="case"><%= micropost.case %></span><br /> 8<span class="timestamp"> 9Posted <%= time_ago_in_words(micropost.created_at) %> ago. 10<% if current_user?(micropost.user) %> 11<%= link_to "delete", micropost, method: :delete, 12data: { confirm: "You sure?" } %> 13<% end %> 14</span> 15<!-- 変更ここから --> 16<span id="like-of-<%= micropost.id %>"> 17 <%= render partial: 'likes/like', locals: { micropost: micropost } %> 18</span> 19<!-- 変更ここまで --> 20</li>

次に、create.js.erb, destroy.js.erbを変更します
・上記のID変更に対応
・partialに渡す変数を修正
どちらも同じで通ると思います。

javascropt

1$("#like-of-<%= @micropost.id %>").html("<%= j(render partial: 'like', locals: { micropost: @micropost}) %>")

最後に作成したerbに合わせてコントローラーを修正します

ruby

1class LikesController < ApplicationController 2 def create 3 # micropostを取得します。(before_actionをしっていたら共通化しましょう) 4 @micropost = Micropost.find(params[:micropost_id]) 5 6 @like = Like.create(user_id: current_user.id, micropost_id: params[:micropost_id]) 7 8 # 以下は多分必要ないので削除 9 # @likes = Like.where(micropost_id: params[:micropost_id]) 10 # @microposts = Micropost.all 11 end 12 13 def destroy 14 # micropostを取得します。(before_actionをしっていたら共通化しましょう) 15 @micropost = Micropost.find(params[:micropost_id]) 16 17 like = Like.find_by(user_id: current_user.id, micropost_id: params[:micropost_id]) 18 like.destroy 19 20 # 以下は多分必要ないので削除 21 # @likes = Like.where(micropost_id: params[:micropost_id]) 22 # @microposts = Micropost.all 23 end 24end

投稿2017/08/24 01:29

編集2018/11/30 02:57
h_daido

総合スコア824

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

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

marutama_giant

2017/08/24 07:41 編集

回答をありがとうございます。試行錯誤してもできなかったので助かります。 _micropost.html.erbで様々なところに呼び出しているのですが、下記が_micropost.html.erbになります。 <li id="<%= micropost.id %>"> <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %> <span class="user"><%= link_to micropost.user.name, micropost.user %></span> <span class="content"><%= micropost.content %></span><br /> <span class="rate rate-<%= micropost.rate %>"></span><br /> <span class="type"><%= micropost.type %></span><br /> <span class="case"><%= micropost.case %></span><br /> <span class="timestamp"> Posted <%= time_ago_in_words(micropost.created_at) %> ago. <% if current_user?(micropost.user) %> <%= link_to "delete", micropost, method: :delete, data: { confirm: "You sure?" } %> <% end %> </span> <!-- like拡張機能 --> <%= render partial: 'likes/like', locals: { micropost: micropost, likes: @likes } %> </li>
h_daido

2017/08/24 09:36

試す環境がないので、机上ではありますが、デバッグしました。 回答本文に追記しているので見てみてください。 試せてないのでエラーでちゃうかもですけど、そしたらまたコメントください。
marutama_giant

2017/08/24 12:48

ありがとうございます。とりあえず、トライしてみます。結果をご報告させていただきます。取り急ぎ失礼いたします。
marutama_giant

2017/08/24 15:05

できました。ありがとうございます 完璧な回答でした、
h_daido

2017/08/25 00:36

よかったです! 余裕があれば引用元のQitaにコメントしておくと良いかなと思います。
TakashiOda

2018/11/29 03:51

同じ問題に苦しんでいたものですが、おかげさまでうまくいきました。 ちなみに一つ質問があるのですが。 _micropost.html.erb 内で <span id="like-of-<%= micropost.id %>"> <%= render partial: 'likes/like', locals: { micropost: micropost, likes: @likes } %> </span> とありますが、likes: @likes の部分は必要あるのでしょうか? 内部で使われていない気がするのですが・・・ もしくは私が初学者なので、私の知識と理解が追いついていないだけなのかどうなのかが気になります。
h_daido

2018/11/30 02:56

> TakashiOdaさん たしかに必要ないですね!
TakashiOda

2018/11/30 07:48

ご返答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問