前説
ここ最近サボっていたので、気を取り直して書いていきます。
非同期通信
https://qiita.com/networkyohan69/items/40cf567880557148d8f4
上記の記事は同期通信を行った時のいいね!取得です。こちらでいいねボタンを押す▶︎リロード▶︎データベースに保存までを実装できました。
いくつか実装パターンがあると思いますが、分類分けしてみました。
Aパターン、Ajaxでゴリゴリ
https://qiita.com/yukisaibai/items/0a84e8c02f423faa7891
上記の方はゴリゴリ書いてらっしゃいます。
メリット
- ajaxの勉強になる
- 応用性が効く
デメリット
- 学習コスト
新しいものにチャレンジしたい人におすすめ
Bパターン、Railsでゴリゴリ
僕はこちらで書いてました。
メリット
- railsをもっと勉強したい
- railsやっている人ならこちらの方が早い?
デメリット
- 応用性
コード
_product.html.erb
<li id="product-<%= a_product.id %>" class="collection-item" >
<span class="timestamp"></span>
<div class="like-button-<%= a_product.id %>">
<%= render 'products/likes' , a_product: a_product %>
</div>
</li>
_like.html.erb
<span class="like">
<% if current_user %>
<% if a_product.user_exist?(current_user) %>
<div class = "action">
<!--すでにいいね!を押してるかどうかの判定 それに応じて画像を変更している-->
<%= form_for [a_product,@like],url: product_like_path(a_product.id,@like.id),method: :delete, remote: true do |f| %>
<%= image_submit_tag("like.png",class: "main_img" )%>
<% end %>
</div>
<% else %>
<div class = "action">
<!--, url: product_likes_path(a_product.id)はpathが複数形なのでなくても良い-->
<%= form_for [a_product, @likes], method: :post, remote: true do |f| %>
<%= image_submit_tag("unlike.png",class: "main_img" ) %>
<% end %>
</div>
<% end %>
<% end %>
</span>
form_for,remote:trueで非同期通信を用いてパスやメソッドを投げている。
create.js
$(".like-button-<%= @product.id %>").html("<%= j(render partial: 'products/likes', locals: { a_product: @product }) %>")
_product.html.erbのclass名を指定して、render先のhtml.erbを読み込んでいる。
destroy.js
$(".like-button-<%= @product.id %>").html("<%= j(render partial: 'products/likes', locals: { a_product: @product }) %>")
_product.html.erbのclass名を指定して、render先のhtml.erbを読み込んでいる。
Bパターンの流れ
- いいね押す
- form_for,remote:trueでデータベースに非同期で変更
- (いいね画像の変更をしてほしい)
- 非同期で_like.html.erbを読み込む
- データベースの情報が反映されていいねの切り替えがうまくできた
Aパターンのコードでは画像の切り替えを行っているが、Bパターンではデータベースの情報を元に非同期でパーションされた部分テンプレートを読み込んでいるという感じですね。
苦戦原因
- どのいいねを押したか、固有のidを取得できない
- $(".like-button-<%= @product.id %>")とすることによってどのいいねボタンのclassを読み込むのか明確化させる
- 最初、なぜかidで指定していた(固有のproduct.idを持つので別にいいが、念のため)
- javascriptが動かない
- render先の_like.html.erbを読み込むはずが、対象の_like.html.erb内のクラスを指定していたので無限ループ状態になっていた。
終わりに
気づいたらBパターンで書いていた。
- Railsのform_forの使い方を見つめ直せたのでよかった。
- rubyがしっかり書けていないなあと猛省。
- javascriptでしっかりコードを書いていきたいなあと思いました。