Ruby on Railsでフォロー機能をつける

Ruby on Railsでフォロー機能を付けていきます。

モデル作成、関連付け

フォロー機能は多対多の関係を持っているので、中間テーブルが必要です。上のような、Reletionshipモデルを作成してください。

次に、モデルの関連付けをしていきます。フォロー機能の関連付けは普通とは少し違い、userモデル同士で関連付けをしていきます。

user.rb

  has_many :following_relationships, foreign_key: "follower_id", class_name: "Relationship", dependent: :destroy
  has_many :followings, through: :following_relationships
  has_many :follower_relationships, foreign_key: "following_id", class_name: "Relationship", dependent: :destroy
  has_many :followers, through: :follower_relationships

relationship.rb

class Relationship < ApplicationRecord
    belongs_to :follower, class_name: "User"
    belongs_to :following, class_name: "User"
    validates :follower_id, presence: true
    validates :following_id, presence: true
end

次に、user.rbにフォローする関数、フォローしているか調べるための関数、フォローを外す関数を作成していきます。

user.rb

  def following?(other_user)
    following_relationships.find_by(following_id: other_user.id)
  end

  def follow!(other_user)
    following_relationships.create!(following_id: other_user.id)
  end

  def unfollow!(other_user)
    following_relationships.find_by(following_id: other_user.id).destroy
  end

最後にルーティングです。

routes.rb 

resources :users do
    member do
     get :following, :followers
    end
end
resources :relationships, :only => [:create, :destroy]

フォローの表示

コントローラーの設定

users_controller.rb

  def following
    @user = User.find_by(id: params[:id])
    @users = @user.followings
    render 'show_follow'
  end

  def followers
    @user  = User.find_by(id: params[:id])
    @users = @user.followers
    render 'show_follower'
  end

relationships_controller.rb 

  def create
    @user = User.find(params[:relationship][:following_id])
    current_user.follow!(@user)
    redirect_to :back
  end

  def destroy
    @user = Relationship.find(params[:id]).following
    current_user.unfollow!(@user)
    redirect_to :back
  end

viewの作成

フォロー一覧、フォロワー一覧ページを作成していきます。

show_follow.html.erb

<% @users.each do |user| %>
<table>
<tr>
  <td>  <%= user.username %> </td>
  <td><%= link_to '詳細', user_path(user) %></td>
</tr>
</table>
<% end %>

show_follower.html.erb

<% @users.each do |user| %>
<table>
<tr>
  <td>  <%= user.username %> </td>
  <td><%= link_to '詳細', user_path(user) %></td>
</tr>
</table>
<% end %>

次に、フォロー数、フォロワー数の表示をしていきます。

_stats.html.erb

<% @user ||= current_user %>
<div class="stats">
  <a href="<%= following_user_path(@user) %>">
    <strong id="following" class="stat">
      <%= @user.followings.count %>
    </strong>
    フォロー
  </a>
  <a href="<%= followers_user_path(@user) %>">
    <strong id="followers" class="stat">
      <%= @user.followers.count %>
    </strong>
    フォロワー
  </a>
</div>

これを、表示したい場所(showページなど)にrenderを使って表示していきます。

users/show.html.erb

<%= render 'stats' %>

フォロー、フォロー解除ボタン

最後に、フォロー、フォロー解除ボタンを作成していきます。これもパーシャルを作り、表示したい場所にrenderで表示していきます。

users/show.html.erbなど

<%= render 'follow_form' %>

_follow_form.html.erb

<% unless current_user?(@user) %>
  <div id="follow_form">
  <% if current_user.following?(@user) %>
    <%= render 'unfollow' %>
  <% else %>
    <%= render 'follow' %>
  <% end %>
  </div>
<% end %>

_follow.html.erb

<%= form_for(current_user.following_relationships.build(following_id: @user.id)) do |f| %>
  <div><%= f.hidden_field :following_id %></div>
  <%= f.submit "フォローする", class: "follow_btn" %>
<% end %>

_unfollow.html.erb

<%= form_for(current_user.following_relationships.find_by(following_id: @user.id), html: { method: :delete }) do |f| %>
  <%= f.submit "Unfollow", class: "btn btn-large follow-btn" %>
<% end %>

以上で、フォロー機能の完成です。