Railsチュートリアル 第14章 ユーザーをフォローする - ステータスフィード実装の動機と計画（データモデルの解説とテストの実装）

# ステータスフィードのデータモデルの基本

例えば、「id 1のユーザーが、id 2、7、8、10のユーザーをフォローしている」という場合、フィードのデータモデルは、`microposts`テーブルのサンプルデータとセットで示すと以下のようなイメージになります。

![User_Feed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323778/40dffc25-2523-cf4e-3920-c42caad28fa1.png)

上図の矢印は、「現在のユーザー自身、および現在のユーザーがフォローしているユーザーに対応するユーザーidを持つマイクロポストを取り出す」という操作を表しています。

# ステータスフィードの要求仕様と、それに対するテスト

## ステータスフィードの要求仕様

どのように実装するかはさておき、この時点では、ステータスフィードの要求仕様として以下を示すことができます。

* ログインユーザー自身のマイクロポストがステータスフィードに含まれていること
* フォローしているユーザーのマイクロポストがステータスフィードに含まれていること
* フォローしていないユーザーのマイクロポストがステータスフィードに含まれていないこと

上記要求仕様をアサーションとして展開し、テストを実装していきましょう。

## 「ステータスフィードを表示する」という機能の実装箇所

「ステータスフィードを表示する」という機能は、Userモデルに`feed`メソッドとして実装したのでしたね。以下に現時点における`app/models/user.rb#feed`の内容を示しておきます。

```ruby:app/models/user.rb#feed
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  # ...略
  def feed
    Micropost.where("user_id = ?", id)
  end
  #...略
end
```

## ステータスフィードのテストの実装

前提条件として、以下のfixtureが存在するものとします。

```yaml:test/fixtures/relationships.yml
one:
  follower: rhakurei
  followed: skomeiji

two:
  follower: rhakurei
  followed: rusami

three:
  follower: skomeiji
  followed: rhakurei

four:
  follower: mkirisame
  followed: rhakurei
```

上記fixtureからは、以下の関係があることがわかります。

* rhakureiはrusamiをフォローしている
* rhakureiはmkirisameをフォローしていない

この状況では、「rhakureiのステータスフィードには、rusamiとrhakureiのマイクロポストは見えるが、mkirisameのマイクロポストは見えない」というのが要求仕様通りの実装となります。

テストの対象はUserモデルなので、テストの実装箇所は`test/models/user_test.rb`となります。以下は実際のテストの実装内容です。

```ruby:test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  #...略

  test "feed should have the right posts" do
    rhakurei  = users(:rhakurei)
    mkirisame = users(:mkirisame)
    rusami  = users(:rusami)
    # フォローしているユーザーの投稿を確認
    rusami.microposts.each do |post_following|
      assert rhakurei.feed.include?(post_following)
    end
    # 自分自身の投稿を確認
    rhakurei.microposts.each do |post_self|
      assert rhakurei.feed.include?(post_self)
    end
    # フォローしていないユーザーの投稿を確認
    mkirisame.microposts.each do |post_unfollowed|
      assert_not rhakurei.feed.include?(post_unfollowed)
    end
  end
end
```

### ステータスフィードのテストの実装に関する、マイクロポストのfixtureの注意事項

※上記テスト「feed should have the right posts」で使用する全てのユーザーについて、1つ以上のマイクロポストを`test/fixtures/microposts.yml`で定義しておく必要があります。1つもマイクロポストを定義していないユーザーがテスト「feed should have the right posts」に含まれていると、テスト「feed should have the right posts」はうまく動きません。

## 当該テストを初めて実装した時点における、ステータスフィードのテストの動作結果

現時点において、`test/models/user_test.rb`を対象としたテストの結果は以下のようになります。

```
# rails test test/models/user_test.rb
Running via Spring preloader in process 127
Started with run options --seed 63017

 FAIL["test_feed_should_have_the_right_posts", UserTest, 3.487605000000258]
 test_feed_should_have_the_right_posts#UserTest (3.49s)
        Expected false to be truthy.
        test/models/user_test.rb:103:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:102:in `block in <class:UserTest>'

  15/15: [=================================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.55564s
15 tests, 27 assertions, 1 failures, 0 errors, 0 skips
```

テストは以下のコードで失敗しています。

```ruby:test/models/user_test.rb（102〜104行目）
rusami.microposts.each do |post_following|
  assert rhakurei.feed.include?(post_following)
end
```

「ログインユーザー自身とは別の、フォローしているユーザーのマイクロポストがフィードに表示されていない」という理由でテストが落ちている、ということになりますね。