Ruby
JavaScript
Rails

タイムラインでいいね機能をつけたい!!~後編~

前説

ここ最近サボっていたので、気を取り直して書いていきます。

非同期通信

https://qiita.com/networkyohan69/items/40cf567880557148d8f4
上記の記事は同期通信を行った時のいいね!取得です。こちらでいいねボタンを押す▶︎リロード▶︎データベースに保存までを実装できました。

いくつか実装パターンがあると思いますが、分類分けしてみました。

Aパターン、Ajaxでゴリゴリ

スクリーンショット 2018-05-04 8.45.02.png

https://qiita.com/yukisaibai/items/0a84e8c02f423faa7891
上記の方はゴリゴリ書いてらっしゃいます。

メリット

  • ajaxの勉強になる
  • 応用性が効く

デメリット

  • 学習コスト

新しいものにチャレンジしたい人におすすめ

Bパターン、Railsでゴリゴリ

スクリーンショット 2018-05-04 8.39.20.png

僕はこちらで書いてました。

メリット

  • 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内のクラスを指定していたので無限ループ状態になっていた。

スクリーンショット 2018-05-04 9.11.29.png

終わりに

気づいたらBパターンで書いていた。
- Railsのform_forの使い方を見つめ直せたのでよかった。 
- rubyがしっかり書けていないなあと猛省。
- javascriptでしっかりコードを書いていきたいなあと思いました。