follow機能の作成

#relationshipモデルの作成

$ rails g model Relationship follower_id:integer following_id:integer


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

```lang: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
これは一度フォローしたユーザーを２度フォローしてしまわないようにするための一意の設定。


#UserとRelationshipの関連付け

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

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

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

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

だから、
belongs_to :following
で
belongs_to :follower



```lang:user.rb

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

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


```lang: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を使う。

```lang: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で取得した集合をより簡単に取り扱うためにメソッドを作成する。


```lang: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と考える。


```lang:user.rb

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

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


```

#ルーティングの設定
```lang: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の表示


```lang: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解除のボタンの作成

ルーティングを設定

```lang:routes.rb

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

```

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

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

$ rails generate controller Relationships


#メソッドの追加

```lang: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の追加

```lang: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のボタンを押した時の集合のページの作成。

順次追加