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


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

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

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

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

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

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

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

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

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

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

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

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

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

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となります。以下は実際のテストの実装内容です。

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

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

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

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