環境
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でレンダリング後に使うローカル変数の設定も忘れずに。
4
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使いました。
結果イメージ
2ヶ月前のメモしたものを書いてるので、色々と忘れてますが、何かおかしなところがありましたらお申し付けください。素人なので間違っていたり回答が遅いかもしれませんが、その辺はご容赦くださいませ。