Help us understand the problem. What is going on with this article?

railsでフォロー機能をつける。

More than 1 year has passed since last update.

メモ

環境
rails 5.0.0
ログイン機能は、deviseで作っている。

フォロー機能つける前の状態

        deviseで、userモデルを作っている。パスワード以下の項目は省略

id 名前  メールアドレス
山田 yamada@yahoo.co.jp
佐藤 satouu@gmail.com
山本 yamamoto@yahoo.co.jp

 

本の登録するために、bookモデルを作っている。 内容は、本のタイトルと感想です。

bookモデル
id 本のid
title 本のタイトル
content 本の感想  
user_id ユーザーid

ターミナルで以下をします。
$rails generate model Relationship follower_id:integer following_id:integer

indexを追加、follower_idとfollowing_idをセットで一意にする。

ruby.20170416132621_create_relationships.rb
class CreateRelationships < ActiveRecord::Migration[5.0]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :following_id

      t.timestamps null: false
    end

    add_index :relationships, :follower_id
    add_index :relationships, :following_id
    add_index :relationships, [:follower_id, :following_id], unique: true
  end
end

マイグレーションをする。

 $rake db:migrate

フォローできるユーザーを取り出すに記述する。(user.following_relationships.followingsをできるようにする)

app/models/user.rb
has_many :following_relationships, foreign_key: "follower_id", class_name: "Relationship", dependent: :destroy

relationships.followingをできるようにする。

app/models/relationship.rb
 belongs_to :following, class_name: "User"
 validates :following_id, presence: true

1対多の関係になる。

フォローしているユーザーを取り出す (user.followingsをできるようにする)

app/models/user.rb
has_many :following_relationships, foreign_key: "follower_id", class_name: "Relationship", dependent: :destroy

has_many :followings, through: :following_relationships
app/models/relationship.rb
    belongs_to :follower, class_name: "User"
    belongs_to :following, class_name: "User"
    validates :follower_id, presence: true
    validates :following_id, presence: true

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

app/models/user.rb
 has_many :following_relationships, foreign_key: "follower_id", class_name: "Relationship", dependent: :destroy

 has_many :followings, through: :following_relationships

  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

フォローされているユーザーを取り出す(user.follwersをできるようにする)

app/models/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

  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

フォロー機能のルーティング

config/routes
 resources :users do
    member do
     get :following, :followers
    end
  end
  resources :relationships,       only: [:create, :destroy]

users/showに、追加

フォローするために、各ユーザーに二つの機能をつける。一つ目は、フォローしている人数とフォローされている人数を示す表示。その数字を押すと、フォローしている/フォローされている人の一覧が出てくる。

二つ目は、このユーザーをフォローする/フォロー解除のボタンである。

s_screenshot 3.png

写真の説明
 一人目のユーザーでログインしている。一つ目のユーザーが、users/showの画面で、ユーザー二人目を見てる。

users/showに追加

deviseでは、user/showは、作られない。だからuser/showをroutesとコントール、viewを付け加える。

デザインは、無視して表示だけ書きます。

app/view/users/show
   <%= render 'follow_form' %>
   <%= render 'stats' %>

app/users/showの説明
renderで他のところから持ってくる。

一つ目のフォローしている人数とフォローされている人数を示す表示。

その数字を押すと、フォローしている、フォローされている人の一覧が出てくる画面を作っていく。

app/views/users/_stats.html.erb
 <% @user ||= current_user %>
<div class="stats">
  <a href="<%= following_user_path(@user) %>">
    <strong id="following" class="stat">
      <%= @user.followings.count %>
    </strong>
    following
  </a>
  <a href="<%= followers_user_path(@user) %>">
    <strong id="followers" class="stat">
      <%= @user.followers.count %>
    </strong>
    followers
  </a>
</div>

app/views/users/_stats.html.erbの説明
この画面で、フォローしている人数とフォローされている人数を表示する。<%= following_user_path(@user) %><%= followers_user_path(@user) %>のリンクがある。これらの二つに対応するcontrollerとviewを作って行く。

app/controllers/users_controller.rb
  def following
      @user  = User.find(params[:id])
      @users = @user.followings
      render 'show_follow'
  end

  def followers
    @user  = User.find(params[:id])
    @users = @user.followers
    render 'show_follower'
  end
app/views/users/show_follow.html.erb
<% @user.followings.each do |user| %>
<table>
<tr>
  <td>  <%= user.username %> </td>
  <td><%= link_to '詳細', user_path(user) %></td>
</tr>

</table>
<% end %>

app/views/users/show_follow.html.erbの説明
  フォローしている人の名前の一覧の画面

app/views/users/show_follower.html.erb
 <% @user.followers.each do |user| %>
<table>
<tr>
  <td>  <%= user.username %> </td>
  <td><%= link_to '詳細', user_path(user) %></td>
</tr>

</table>
<% end %>

app/views/users/show_follower.html.erbの説明
フォローされている人の一覧画面

補足説明 routesは、これでやっています。

config/routes.rb
  resources :users do
    member do
     get :following, :followers
    end
  end

これで、フォローしている人数とフォローされている人数をカウント表示と一覧は完成です。

二つ目の機能を作る。他のユーザーのフォロー、フォローを解除する。

config/roures.rb
   resources :relationships, only: [:create, :destroy]
app/views/users/_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 %>  
app/helpers/users_helper.rb
  def current_user?(user)
     user == current_user
  end

app/views/users/_follow_form.html.erbの説明
 一行目<% unless current_user?(@user) %>
このコードで、現在ログインしているユーザーのプロフィールは、フォロー、フォロー解除のボタンが出ないようにする。

三行目からのifの説明。
ユーザーがフォローしている場合は、フォロー解除ボタンを表示。
してない場合は、フォローボタン表示させる。

フォローボタン、フォロー解除のボタンの機能

app/views/users/_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 %>
app/views/users/_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 "Follow", class: "btn btn-large btn-primary follow-btn" %>
<% end %>
app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController

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

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

これで完成。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした