10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

follow機能の作成

Last updated at Posted at 2016-02-20

#relationshipモデルの作成

$ rails g model Relationship follower_id:integer following_id:integer

#20160220133958_create_relationships.rbのにインデックスとか追加

20160220133958_create_relationships.rb

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

add_index :relationships, [:follower_id, :following_id], unique: true
これは一度フォローしたユーザーを2度フォローしてしまわないようにするための一意の設定。

#UserとRelationshipの関連付け

まず、フォローするのとフォローされるのとで能動的関係と受動的関係で分けることをする。
ここでは能動的関係をactive_relationshipと呼び、受動的関係をpassive_relationshipと呼ぶことにする。
最初にactive_relationshipの方から進めていく。

まずはuserから見たもの考える。
一人のユーザーにはたくさんのfollowerがいるからhas_many。

今度はrelationshipから見たものを考える。

followingから見てfollowingしているのはユーザー1人。
followerから見てfollowerしているのはユーザー1人。

だから、
belongs_to :following

belongs_to :follower

user.rb

has_many :active_relationships,class_name:  "Relationship", foreign_key: "follower_id", dependent: :destroy

フォローしているユーザーをfollower_idを外部キーとして特定する。

Relationship.rb
  belongs_to :follower, class_name: "User"
  belongs_to :following, class_name: "User"

#こうすればこれだけのメソッドが使えるようになる。

active_relationship.follower フォロワーを返す
active_relationship.following フォローしているユーザーを返す
user.active_relationships.create(following_id: user.id) userを紐付けて能動的関係を作成/登録する
user.active_relationships.create!(following_id: user.id) userを紐付けて能動的関係を作成/登録する (失敗時にエラーを出力)
user.active_relationships.build(following_id: user.id) userと紐付けた新しいRelationshipオブジェクトを返す

#フォローしているユーザー
1人のユーザーにはいくつもの「フォローする/される (多対多)」のリレーションシップがある。
なのでhas_many throughを使う。

user.rb

  has_many :following, through: :active_relationships, source: :following

railsはfollwingを見てrelationshipsテーブルのfollowing_idを使って対象のユーザーを取得してくる。
source:はなくても良いがわかりやすくするために書居ておいた。
実際はマジでいらない。

これでuser.followingが使えるようになる。

この関連付けにより、フォローしているユーザーを配列の様に扱えるようになった。

例えば、include?メソッドを使ってフォローしているユーザーの集合を調べてみたり、関連付けを通してオブジェクトを探しだせるようになった。

user.following.find(other_user)でフォローしているユーザーを取り出せるようになった。

#followやunfollowなどのメソッドの追加

followingで取得した集合をより簡単に取り扱うためにメソッドを作成する。

user.rb

  # ユーザーをフォローする
  def follow(other_user)
    active_relationships.create(following_id: other_user.id)
  end

  # ユーザーをアンフォローする
  def unfollow(other_user)
    active_relationships.find_by(following_id: other_user.id).destroy
  end

  # 現在のユーザーがフォローしてたらtrueを返す
  def following?(other_user)
    following.include?(other_user)
  end

user.followersメソッドを作成する

これは上のuser.followingメソッドと対になるやつ。

follower_idとfollowing_idを入れ替えるだけで、フォロワーについてもユーザーのフォローのときとまったく同じ方法が使用できる。

followerなので、フォローされていると考え、受動的関係と考え、passive_relationshipと考える。

user.rb

    has_many :passive_relationships, class_name: "Relationship", foreign_key: "following_id", dependent: :destroy

    has_many :followers, through: :passive_relationships, source: :follower


#ルーティングの設定

routes.rb

  resources :users do
    member do
     get :following, :followers
    end
  end

following_user GET /users/:id/following(.:format) users#following
followers_user GET /users/:id/followers(.:format) users#followers

このルーティングができる。

#followerとfollowingの表示

show.html.erb

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

#follow
とfolow解除のボタンの作成

ルーティングを設定

routes.rb

resources :relationships, only: [:create, :destroy]

ボタンのviewはもうちょと後で書く。

その前に
#コントローラーの作成

$ rails generate controller Relationships

#メソッドの追加

relationships_controller.rb

def create
    user = User.find(params[: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


#ボタンのviewの追加

show.html.erb
<%= form_for(current_user.active_relationships.build) do |f| %>
  <div><%= hidden_field_tag :following_id, @user.id %></div>
  <%= f.submit "Follow", class: "btn btn-primary" %>
<% end %>


あとはフォロー解除のボタンと、
followとfollowerのボタンを押した時の集合のページの作成。

順次追加

10
10
1

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
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?