Category : Ruby

フォロー機能を実装してみようと思うのでメモ。
自分で作ろうとも思ったけど「party_boy」というライブラリが良さげだったのでそれを利用してみた。

事前準備

#Gemfile
gem 'party_boy'
bundle install
rails g party_boy

この時マイグレーションファイルが作成されるので、rake db:migrate したらエラーが出てほげぇ。
どうやら作成されたマイグレーションファイルのclass名が間違っているらしく、手動で修正しなきゃだめらしい。

# db/migrate/xxxxxxxxxxxxxx_create_relationship.rb
# class名を "CreateRelationship" に変更
class CreateRelationship < ActiveRecord::Migration

マイグレーションして、これで導入は完了。

Model

# app/models/user.rb
# 追記
acts_as_followable
# app/models/relationship.rb
# 追記
attr_accessible :requestor, :requestee, :restricted

# バリデーションを追記
validate do
  if requestor.id == requestee.id
    return errors.add(:requestor)
  end
end

requestor がフォローする人で、requestee がフォローされる人。
これらのidが一緒だった場合はエラーを返すようにする。これもライブラリ側でやってくれればいいのになーと。
attr_accessible の指定もデフォルトでは記述されていないので忘れずに。私はここで軽くハマりました・・・

Controller

下記でフォロー/フォロワーを取得。

# app/controllers/users_controller.rb
# フォローしているユーザー
@friendship[:follow] = @user.following
# フォローされているユーザー
@friendship[:follower] = @user.followers
# フォローしているか調べる
@user_a.following?(@user_b)
# フォローされているか調べる
@user_b.followed_by?(@user_a)

フォロー/アンフォローの動作。

# app/controllers/users_controller.rb
def action_follow
  # ログインチェック
  raise unless current_user

  @user = User.find(params[:requestee_id])

  # 既にフォローしているかチェック
  if current_user.following?(@user)
    render friend_unfollow(@user)
  else
    render friend_follow(@user)
  end

  rescue
  render :json => {:result => "error" }, :status => 400
end

def friend_follow(user)
  current_user.follow(user)
  return  { :json => { :type => "add", :result => "success" } }
  rescue
  return  { :json => { :type => "add", :result => "error" } }
end

def friend_unfollow(user)
  current_user.unfollow(user)
  return  { :json => { :type => "remove", :result => "success" } }
  rescue
  return  { :json => { :type => "remove", :result => "error" } }
end

前回のスター追加と同じように1URLで実装したかったので、コントローラ内での分岐にしてみた。

あとはJSをうんぬんかんぬんすれば、twitterlikeなフォローボタンの出来上がりです。

参考