Ruby
Ajax
RubyOnRails

お気に入り(いいね)機能をajaxで投稿のindexページにつけてみる。(ajaxがメインです)

環境
Rails 5.1.1
Ruby 2.3.0

前提条件

userテーブルに紐づいたblogテーブルがあること(1:多)。
userとblogの中間テーブルのfavoriteがあること(多:多)
お気に入り機能をすでに実装済みであること。(user_id,blog_idの値をレコードをfavoriteテーブルに保存する処理)

流れ

1、送信方法をdata-remote: trueにする。
2、お気に入りボタンを変更する。
3、favorites_controllerをJSを対応した設定にする。
4,JSファイルを作成し、indexページのお気に入り部分を動的に処理する記述をする。

1

views/favorites/_favorite.htm.erb

<% favorite = current_user.favorites.find_by(blog_id: blog.id) %>
<% if favorite.present? %>
  <%= link_to favorite_path(id: favorite.id), method: :delete, remote: true, class: "glyphicon glyphicon-heart", style:"color: red"do %><% end %>
<% else %>
  <%= link_to favorites_path(blog_id: blog.id),method: :post, remote: true, class: "glyphicon glyphicon-heart-empty" do%><% end %>
<% end %>

remote: tureの送信方法にしてください。Ajaxを使用するため。このファイルはindex.html.erbに描画(レンダリング)されるお気に入りボタンです。

2

views/blogs/index.html.erb

<%= @blogs.each do |blog| %>

~省略

<div id="favorite_btn_<%= blog.id %>">
  <%= render partial: "favorites/favorite", locals: {blog: blog} %>
</div>

<% end %>

ここのidが後々のJSで要素を取得するターゲットになります。idの末尾の<%= blog.id %>の記述は、どの投稿かを区別するため。renderにより_favorites.html.erbを描写(レンダリング)しています。 locals: {blog: blog}はレンダリング元にローカル変数を渡す設定です。locals: {ローカル変数: 代入したい値}

3

controllers/favorites_controller

def create
    @favorite = current_user.favorites.create(picture_id: params[:blog_id])
    @blog = Blog.find(params[:blog_id])

    respond_to do |format|
    format.js {render :template => "blogs/index",locals: { favorite: @favorite, blog: @blog} } 
    end
end

repond_to do |format|によりファイル名.js.erbになってものを探してきてくれる。
renderに:templateオプションで別のコントローラのviewをレンダリングできる。view/blogs/create.js.erbを探しに行ってくれる。http://railsdoc.com/references/render
これしないとview/favorites/create.jsを探しちゃいます。あとlocalsでレンダリング後に使うローカル変数の設定も忘れずに。

view/blogs/create.js.erb

$("#favorite_btn_<%= favorite.blog_id %>").html("<%= j(render 'favorites/favorite',{favorite: favorite, blog: blog})%>");

1の_favorite.html.erbにレンダリングしてます。レンダリング先でお気入りボタンの条件分岐の処理(お気に入りされいるか否か?)をしているので、ここでもローカル変数の設定。JSだとlocalsとは書かないみたいなので、記述の違いに注意。
これで完成。お気入りのボタンはbootstrapのglyphicon使いました。

結果イメージ

https://gyazo.com/bcc77e5dc4e8fb83f1fcdd34a1c531e0

2ヶ月前のメモしたものを書いてるので、色々と忘れてますが、何かおかしなところがありましたらお申し付けください。素人なので間違っていたり回答が遅いかもしれませんが、その辺はご容赦くださいませ。