なつねこメモ

主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ

書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。

2016/02/08

Rails でフォロー機能を実装したい

カテゴリー:RubyRuby on Rails

すでに情報が腐るほどあるフォロー機能ですが、理解を深めるためにも、
自分の言葉でまとめ直してみます。


Rails で、 Twitter や app.net などにある、ユーザーどうしのフォロー機能を
実装したいとします。
どうやら、いい感じの gem が存在しているようですが、今回は使わない方針で。

フォロー機能を実装しようと思うと、ユーザーとユーザーの多対多の関係となるため、
以下の様な DB 構成になると思います。
(Relation は中間テーブル)

 User                Relation                  User
+----------------+  +--------------------+  +-------
| id:   integer  |  | target_id: integer |  | id:
| name: string   +--+ from_id:   integer +--+ name:
| ...            |  |                    |  | ...
+----------------+  +--------------------+  +-------

UserA(id:1)UserB(id:2) をフォローした場合は、
Relationtarget_id: 2, from_id: 1 が挿入される感じです。

ということで、早速実装。
モデルを作って。

$ rails g model relation

マイグレーションファイルをいじる。

db/migration/20160201094212_create_relations.rb

class CreateRelations < ActiveRecord::Migration
  def change
    create_table :relations do |t|
      t.integer target_id, null: false
      t.integer from_id,   null: false
    end
  end
end

そして適用。

$ bundle exec rake db:migrate

次に、 Model に has_many とかつけていきます。

app/models/user.rb

class User < ActiveRecord::Base
  has_many :follows_f, class_name: 'Relation', foreign_key: :from_id
  has_many :followings, through: :follows_f, source: 'target'

  has_many :followers_f, class_name: 'Relation', foreign_key: :target_id
  has_many :followers, through: :followers_f, source: 'from'

  # ...
end

中間テーブルも。

app/models/relation.rb

class Relation < ActiveRecord::Base
  belongs_to :target, class_name: 'User', foreign_key: 'target_id'
  belongs_to :from, class_name: 'User', foreign_key: 'from_id'
end

これで、上に示した DB の関連を実装できました。
次に、フォローなどの機能を追加していきます。

app/models/user.rb

class User < ActiveRecord::Base
  ...

  def follow user
    followings << user
  end

  def unfollow user
    followings.destroy user
  end

  def followed? user
    followings.include? user
  end

  def follower? user
    user.followers.include? user
  end
end

これでおわり。