railsチュートリアル第十四章 フォロワー

###フォロワー
####受動的関係を使ってuser.followersを実装する
app/models/user.rb

```rb
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  # 他のモデルとの間に「1対多」のつながり
  # has_many関連付けが使われている場合、
  #   「反対側」のモデルでは多くの場合belongs_toが使われます。
  # dependent: :destroy
  # ユーザーが破棄された場合
  #   、ユーザーのマイクロポストも同様に破棄される。
  has_many :active_relationships, class_name:  "Relationship",
  # :active_relationsshitpsデータモデル 能動的関係(フォローしているがフォローはされていない関係)
  # class_name: テーブル名 "Relationship"
                                  foreign_key: "follower_id",
                                  # foreign_key: 外部キー
                                  #   データベースの二つのテーブルを繋げる
                                  # Micropostモデルとrelationshipsモデルを繋げる
                                  dependent:   :destroy
                                  # ユーザーが削除されるとマイクロポストも削除される
  has_many :passive_relationships, class_name:  "Relationship",
  # passive_relationsshipsデータモデル 受動的関係（フォローされている）
  # class_name: テーブル名 Relationsship
                                   foreign_key: "followed_id",
                                   # 外部キー  テーブル同士の紐づけに用いるカラムのこと。
                                   dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed
  # :following followingデータモデル 
  # has_many :through関連付けは、他方のモデルと「多対多」のつながりを設定する場合によく使われます。
  # この関連付けは、2つのモデルの間に「第3のモデル」(joinモデル)が介在する点が特徴です。
  # フォローするには:active_relationshipsデータモデルが介在する
  # source: following配列の元はfollowed idの集合である
  has_many :followers, through: :passive_relationships, source: :follower
  # folloersデータモデル
  # userとfollowersの間にはpasseive_relationsshipsが介在する
  # souce: 関連付けにおける「ソースの」関連付け名、つまり関連付け元の名前を指定します。
  # 関連づけ名とは関連付けたいデータモデルの名前
  #   この場合 :followerが関連付けられる
.
.
.
end
```

####followersに対するテスト
test/models/user_test.rb

```rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
.
.
. 
  test "should follow and unfollow a user" do
    michael = users(:michael)
    # テストユーザーを代入
    archer  = users(:archer)
    assert_not michael.following?(archer)
    # archerはmichaelをふぉろーしていないことを確認
    michael.follow(archer)
    # archerをフォロー
    assert michael.following?(archer)
    # フォローしているか？
    assert archer.followers.include?(michael)
    # archerのフォロワーの中にmichaelは入っているか？
    michael.unfollow(archer)
    assert_not michael.following?(archer)
  end
end
```

####テスト
```
ubuntu:~/environment/sample_app (following-users) $ rails t
Running via Spring preloader in process 8487
Started with run options --seed 30377

  63/63: [==============================] 100% Time: 00:00:08, Time: 00:00:08

Finished in 8.39715s
63 tests, 320 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.
コンソールを開き、何人かのユーザーが最初のユーザーをフォローしている状況を作ってみてください。最初のユーザーをuserとすると、user.followers.map(&:id)の値はどのようになっているでしょうか?

```rb
>> user = User.first
  User Load (1.7ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2021-10-27 07:03:00", updated_at: "2021-10-27 07:03:00", password_digest: [FILTERED], remember_digest: nil, admin: true, activation_digest: "$2a$12$i2cTpO7yNDagp6oMpVyIq.lyvQ1yEuoSJsOj7G9qZaX...", activated: true, activated_at: "2021-10-27 07:03:00", reset_digest: nil, reset_sent_at: nil>
>> user2 = User.second
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ?  [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Isaias Ebert", email: "example-1@railstutorial.org", created_at: "2021-10-27 07:03:01", updated_at: "2021-10-27 07:03:01", password_digest: [FILTERED], remember_digest: nil, admin: false, activation_digest: "$2a$12$2NxDk9cW24wyZiN3f4LI7OI3D6NSgj7mvZ/huoEFRbE...", activated: true, activated_at: "2021-10-27 07:03:00", reset_digest: nil, reset_sent_at: nil>
>> user3 = User.third
  User Load (0.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ?  [["LIMIT", 1], ["OFFSET", 2]]
=> #<User id: 3, name: "Freddy Hills Jr.", email: "example-2@railstutorial.org", created_at: "2021-10-27 07:03:01", updated_at: "2021-10-27 07:03:01", password_digest: [FILTERED], remember_digest: nil, admin: false, activation_digest: "$2a$12$LkEsBxgeobFCiJ3ssmWkZ.AxMinGX35D2x4yas988fL...", activated: true, activated_at: "2021-10-27 07:03:01", reset_digest: nil, reset_sent_at: nil>
>> user.active_relationships.create(followed_id: user2.id)
   (0.1ms)  begin transaction
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  Relationship Create (2.5ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 1], ["followed_id", 2], ["created_at", "2021-10-28 14:07:57.360763"], ["updated_at", "2021-10-28 14:07:57.360763"]]
   (7.1ms)  commit transaction
=> #<Relationship id: 2, follower_id: 1, followed_id: 2, created_at: "2021-10-28 14:07:57", updated_at: "2021-10-28 14:07:57">
>> user.active_relationships.create(followed_id: user3.id)                   
   (0.1ms)  begin transaction
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  Relationship Create (1.6ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 1], ["followed_id", 3], ["created_at", "2021-10-28 14:08:02.784912"], ["updated_at", "2021-10-28 14:08:02.784912"]]
   (9.7ms)  commit transaction
=> #<Relationship id: 3, follower_id: 1, followed_id: 3, created_at: "2021-10-28 14:08:02", updated_at: "2021-10-28 14:08:02">
>> user.followers.map(&:id)
Traceback (most recent call last):
        1: from (irb):17
NoMethodError (undefined method `followers' for #<User:0x000055e039bd2a80>)
Did you mean?  follow
               following
>> user.followers.map(&:id)
Traceback (most recent call last):
        2: from (irb):18
        1: from (irb):18:in `rescue in irb_binding'
NoMethodError (undefined method `followers' for #<User:0x000055e039bd2a80>)
>> user.followers.count
Traceback (most recent call last):
        2: from (irb):19
        1: from (irb):19:in `rescue in irb_binding'
NoMethodError (undefined method `followers' for #<User:0x000055e039bd2a80>)
>> user.followers.map(&:id)
Traceback (most recent call last):
        2: from (irb):20
        1: from (irb):20:in `rescue in irb_binding'
NoMethodError (undefined method `followers' for #<User:0x000055e039bd2a80>)
>> user.following.map(&:id)
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> [2, 3]
```

2.
上の演習が終わったら、user.followers.countの実行結果が、先ほどフォローさせたユーザー数と一致していることを確認してみましょう。

```
>> user.following.count
   (0.2ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> 2
```

3.
user.followers.countを実行した結果、出力されるSQL文はどのような内容になっているでしょうか? また、user.followers.to_a.countの実行結果と違っている箇所はありますか? ヒント: もしuserに100万人のフォロワーがいた場合、どのような違いがあるでしょうか? 考えてみてください。

```
FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> 2
```
uesrsからrelationshipsに繋がれた。　フォローされているidカラムとフォローしているカラム

```rb
>> user.following.to_a.count
=> 2
```
SQL文が表示されない