LoginSignup
6
1

More than 3 years have passed since last update.

railsでフォロー機能を非同期化する

Posted at

開発環境

Mac OS Catalina 10.15.7
ruby 2.6系
rails 6.0系

前提

・フォロー機能は実装済み(フォロー機能に関するgemは使用していません)
・フォロー機能を実装する際の中間テーブ名はrelationshipsテーブル

フォロー機能に関しては下記のURLの記事を参考に実装すると良いかと思います。
理解しやすくまとめてくれています。
https://qiita.com/mitsumitsu1128/items/e41e2ff37f143db81897

フォローボタン部分を部分テンプレートで切り出す

まずはフォローボタンを部分テンプレートで切り出します。
後にcreate.jsとdestroy.jsでこの部分テンプレートを差し替えるためです。

自分はsharedディレクトリを作っているので、その中に切り出しました。

views/users/show.html.erb
# 自分はユーザー詳細ページにフォローボタンを設置しています。
<% if user_signed_in? && current_user.id != @user.id %>
  <div>
    <%= render "shared/follow", user: @user %>
  </div>
<% end %>
views/shared/_follow.html.erb

  <% if current_user.following?(user) %>
    <%= form_for(current_user.relationships.find_by(follow_id: user.id), html: { method: :delete }) do |f| %>
      <%= hidden_field_tag :follow_id, user.id %>
      <%= f.submit 'フォロー解除', class: 'btn btn-danger btn-block' %>
    <% end %>
  <% else %>
    <%= form_for(current_user.relationships.build) do |f| %>
      <%= hidden_field_tag :follow_id, user.id %>
      <%= f.submit 'フォローする', class: 'btn btn-primary btn-block' %>
    <% end %>
  <% end %>

切り出した部分テンプレートの親要素にIDを付与

後にjs.erbファイルでこのIDを取得して、中身を差し替えるためです。

views/users/show.html.erb
<% if user_signed_in? && current_user.id != @user.id %>
  # 下記1行にIDを付与
  <div id="follow-ajax">
    <%= render "shared/follow", user: @user %>
  </div>
<% end %>

form_forをremote: trueにする

form_forをremote: trueにします。

form_forはform_withと異なり、デフォルトでremote: trueになっているわけではないので、非同期にしたい場合はremote: trueを記述してあげる必要があります。

views/shared/_follow.html.erb

    # 次の1行にremote: trueを追加
    <%= form_for(current_user.relationships.find_by(follow_id: user.id), html: { method: :delete },remote: true) do |f| %>


    # 次の1行にremote: trueを追加
    <%= form_for(current_user.relationships.build, remote: true) do |f| %>

コントローラーのリダイレクトの記述を削除

コントローラーでリダイレクトの記述をしている場合は削除します。
なければスルーで大丈夫です。

relationships_controller.rb
 def create
    following = current_user.follow(@user)
    following.save
    # リダイレクトの記述があれば削除する
  end

  def destroy
    following = current_user.unfollow(@user)
    following.destroy
    # リダイレクトの記述があれば削除する
  end

create.jsとdestroy.jsを編集する

どちらもコードは同じです。

前述のように自分はsharedディレクトリに部分テンプレートを入れているので、partialオプションの記述が'shared/follow'となります。
また、localsオプションで、切り出した部分テンプレート内で使う変数をしっかりと渡してあげましょう。

create.js.erb
document.getElementById('follow-ajax').innerHTML = '<%= j(render partial: 'shared/follow', locals: { user: @user }) %>
destroy.js.erb
document.getElementById('follow-ajax').innerHTML = '<%= j(render partial: 'shared/follow', locals: { user: @user }) %>

以上です。
参考になれば幸いです。

6
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1