Ruby
Rails

acts_as_followerを使ってフォロー/フォロワー機能を実装

前説

フォロー、フォロワー機能を実装しました。
イメージとしてはデータベースのテーブル関係とはどうするんだろうとかと、ハードル高そうに感じていました。
しかしgemを用いると結構すぐに実装できました。

実装

  • 非同期でフォロー、フォロワー機能を実装

コード

以下のgemを導入します。

gem 'acts_as_follower'
  follow_users POST   /users/:id/follow(.:format)                  users#follow 
unfollow_users POST   /users/:id/unfollow(.:format)                users#unfollow

導入部に関してはこちらを参考にして頂けた方がわかりやすいかと思います。

気になっていたデータベースとつなぐmodelの部分。

model/follow.rb
class Follow < ActiveRecord::Base

  extend ActsAsFollower::FollowerLib
  extend ActsAsFollower::FollowScopes

  # NOTE: Follows belong to the "followable" interface, and also to followers
  belongs_to :followable, :polymorphic => true
  belongs_to :follower,   :polymorphic => true

  def block!
    self.update_attribute(:blocked, true)
  end

end

ここで知らないデータベース関連がでてきました。

polymorphic => true

followerとfollowableの二つの情報があるのに対し、用意されているテーブルは一つだけ。
つまり、フォローもフォロワーも親クラスから見た操作や情報がほとんど同じである為、一つのテーブルにまとめてしまおうというものらしい。
https://shirusu-ni-tarazu.hatenablog.jp/entry/2012/11/04/173742
↑参考記事

model/user.rb
class User < ApplicationRecord
  acts_as_followable # フォロワー機能
  acts_as_follower   # フォロー機能
end

cotroller/user_controller.rb
def follow
    @user = User.find(params[:id])
    #ログイン中のユーザーで対象のユーザー(@user)をフォローする
    current_user.follow(@user)
end

def unfollow
    @user = User.find(params[:id])
    #ログイン中のユーザーで対象のユーザー(@user)をフォロー解除する
    current_user.stop_following(@user)
end
user/show.html.erb
<li id="user-<%= @user.id %>" class="collection-item">
    <%= render 'users/follow', user: @user %>
</li>
user/_follow.html.erb
#任意のユーザーのマイページにて
#マイページのユーザーが現在ログインしているユーザーでない時->フォロー/フォロワーボタンを設置
<% if user.id != current_user.id %>
  <li class="collection-item">
    #現在のユーザーが対象のユーザーをフォローしてない時->「フォローするボタン」を設置
    <% unless current_user.following?(user) %>
      <div class="action">
         <%= link_to 'フォローする' ,follow_users_path,method: :post, class: "btn waves-effect waves-light" ,remote: true %>
      </div>
    #現在のユーザーが対象のユーザーをフォローしてる時->「フォロー解除ボタン」を設置
    <% else %>
      <div class="action">
         <%= link_to 'フォローを解除する' ,unfollow_users_path, method: :post,class: "btn waves-effect waves-light",remote: true %>
      </div>
    <% end %>
  </li>
<% end %>
follow.js.erb
$("#user-<%= @user.id %>").html("<%= j(render partial: 'users/follow', locals: { user: @user }) %>")
unfollow.js.erb
$("#user-<%= @user.id %>").html("<%= j(render partial: 'users/follow', locals: { user: @user }) %>")

結果

スクリーンショット 2018-05-08 23.32.15.png

フォローするでしょ

終わりに

感じたこととしてはいいね機能の実装と近い感じがしました。

今後の実装

  • フォロワーの数を数えてランキングにもしたい
  • フォローしているユーザーによるタイムラインの実装とか