【Rails】【非同期通信】create.js.hamlがうまく機能しない=>create.js.erbにすることで解決(したように見えた初歩的ミス)
実装したかった機能
いいね!機能を実装しようと思い、非同期通信でいいね!を送信して結果を部分テンプレートで更新させようとしました。
具体的な流れとしては、部分テンプレートで作成したいいねボタンをクリックすることで非同期通信によりいいねの作成・削除を行い、結果に基づきいいねボタン(部分テンプレート)を更新させるという手順を想定しました。
開発環境
Ruby: 2.5.1
Rails: 5.2.3
うまくいかなかったコード
モデル
class User < ApplicationRecord
# (中略)
has_many :likes
has_many :items
end
class Item < ApplicationRecord
# (中略)
has_many :likes
def liked?(user)
likes.where(user_id: user.id).exists?
end
end
class Like < ApplicationRecord
belongs_to :user
belongs_to :item
validates :user_id, presence: true
validates :item_id, presence: true
validates_uniqueness_of :item_id, scope: :user_id
end
コントローラー
class ItemsController < ApplicationController
# (中略)
def show
@item = Item.find(params[:id])
@likes_count = @item.likes.length
end
end
class LikesController < ApplicationController
before_action :item_setting
def create
@like = current_user.likes.new(item_id: params[:item_id])
if @like.save
return_likes_count
else
return_error
end
end
def destroy
if @like = current_user.likes.find_by(item_id: params[:item_id])
if @like.destroy
return_likes_count
else
return_error
end
else
return_error
end
end
private
def item_setting
@item = Item.find(params[:item_id])
end
def return_likes_count
@likes_count = @item.likes.length
end
def return_error
@likes_count = "err"
end
end
ビュー
// (前略)
#likes
= render partial: "likes", locals: {item: @item}
// (後略)
// このファイル内の「@item」は「item」とした方が正確な書き方かもしれません
- if user_signed_in? && @item.liked?(current_user)
= link_to item_likes_path(@item.id), method: :delete, remote: true do
%li.items-tag__left--good{id: "good_btn_liked"}
= icon('far', 'heart')
%span いいね!
%span#likes_count
= @likes_count
- elsif user_signed_in?
= link_to item_likes_path(@item.id), method: :post, remote: true do
%li.items-tag__left--good{id: "good_btn"}
= icon('far', 'heart')
%span いいね!
%span#likes_count
= @likes_count
- else
%li.items-tag__left--good{id: "#{'good_btn' if user_signed_in?}"+"#{'_liked' if user_signed_in? && current_user.likes.exists?(item_id: @item.id)}"}
= icon('far', 'heart')
%span いいね!
%span#likes_count
= @likes_count
// これらのファイルがエラーの原因でした
$('#likes').html(“#{j(render partial: "items/likes", locals: { item: @item })}");
発生したエラー
いいねボタンをクリックすると、コンソールで以下のエラーが確認できました。
Uncaught SyntaxError: Invalid or unexpected token VM3330:1
at processResponse (rails-ujs.self-43e81c501e7e36871a34b4b950451cc7cb047af4e846ec742539e64724582452.js?body=1:273)
at rails-ujs.self-43e81c501e7e36871a34b4b950451cc7cb047af4e846ec742539e64724582452.js?body=1:201
at XMLHttpRequest.xhr.onreadystatechange (rails-ujs.self-43e81c501e7e36871a34b4b950451cc7cb047af4e846ec742539e64724582452.js?body=1:256)
ここでレスポンスの内容を確認すると、部分テンプレートの更新部分は以下のようになっていたようです。
$('#likes').html(“<a data-remote=\"true\" rel=\"nofollow\" data-method=\"delete\" href=\"/items/5/likes\"><li class=\'items-tag__left--good\' id=\'good_btn_liked\'>\n<i class=\"far fa-heart\"><\/i>\n<span>いいね!<\/span>\n<span id=\'likes_count\'>\n3\n<\/span>\n<\/li>\n<\/a>");
^ よく見るとここの記号がダブルクォート(")じゃない。なにこれ?
エラーが出ている時には気付きませんでしたが、よく見ると.html()内最初のダブルクォートが違う記号になっており、これがエラーの原因となっていました。何故?
修正したコード
<%# ファイル形式をhamlからerbに変更しました %>
$('#likes').html("<%= j(render partial: 'items/likes', locals: {item: @item}) %>");
結果
無事にエラーが解消されました。以下はcreate.js.erbから返ってきたレスポンスの内容です。
$('#likes').html("<a data-remote=\"true\" rel=\"nofollow\" data-method=\"delete\" href=\"/items/5/likes\"><li class=\'items-tag__left--good\' id=\'good_btn_liked\'>\n<i class=\"far fa-heart\"><\/i>\n<span>いいね!<\/span>\n<span id=\'likes_count\'>\n3\n<\/span>\n<\/li>\n<\/a>");
ファイル形式をhamlからerbに変更することで、返ってくるコードのダブルクォートが正しいものになり、エラーなく動いてくれる様になったようです。
".js.haml"
でググってみたところいくつか記事はヒットしたのですが、参考にしてもどうも上手くいきませんでした。
今までのビューを全てhamlで書いていたため、create.js、destroy.jsもhamlで書こうとしていましたが、どうもこれが良くなかったみたいです。
同じようなコードに思えるのですが、まだまだ分からないことだらけですね。
追記
記事の投稿後に改めて確認すると、元々create.js.hamlで書いていたコードですでにダブルクォートじゃなくなってました。
他のアプリを作成中にhamlで同じことを試したら問題なく動作しました。
他のサイトを見ながらコピペしていたのか、何にせよhamlのせいではないようです。
他人のコードのコピペはいろんな意味でよくないですね。
参考
Author And Source
この問題について(【Rails】【非同期通信】create.js.hamlがうまく機能しない=>create.js.erbにすることで解決(したように見えた初歩的ミス)), 我々は、より多くの情報をここで見つけました https://qiita.com/iiyama_makoto/items/311e92ead5be18b6c8d4著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .