Ruby on Rails チュートリアル 第14章 ステータスフィード


ステータスフィードについて

 ここでは、ユーザーのHomeページで表示されるステータスフィード(タイムライン)の実装及びテストについて説明する。
 ステータスフィードでは現在のユーザーにフォローされているユーザー及び自身のマイクロポストを表示する。まず、フィードの実装に入る前にテストを書いておく。テストでは、1) フォローしているユーザーのマイクロポストがフィードに含まれていること。2) 自分自身のマイクロポストもフィードに含まれていること。3) フォローしていないユーザーのマイクロポストがフィードに含まれていないこと。の3つの要件が満たされているかを確認する。以下がそのようなテストのコードである。

test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase
  .
  .
  .
  test "feed should have the right posts" do
    michael = users(:michael)
    archer  = users(:archer)
    lana    = users(:lana)
    # フォローしているユーザーの投稿を確認
    lana.microposts.each do |post_following|
      assert michael.feed.include?(post_following)
    end
    # 自分自身の投稿を確認
    michael.microposts.each do |post_self|
      assert michael.feed.include?(post_self)
    end
    # フォローしていないユーザーの投稿を確認
    archer.microposts.each do |post_unfollowed|
      assert_not michael.feed.include?(post_unfollowed)
    end
  end
end

上記のテストでは、fixtureファイルでmichaelがlanaをフォローし、archerをフォローしていないことが前提となっており、lanaと自身のマイクロポストがmichaelのフィードに表示されていること、およびarcherのマイクロポストがmichaelのフィードに表示されていないことを確認している。
 つぎに、このテスト内で使用されているフィードメソッドの実装に移る。フィードメソッドの機能としては、micropostsテーブルから、自分がフォローしているユーザーのユーザーIDをもつマイクロポストデータと、自身のユーザーIDをもつマイクロポストデータを取得し、返すことができればよい。これを実装すると以下のようになる。

app/models/user.rb
class User < ApplicationRecord
  .
  .
  .
  # ユーザーのステータスフィードを返す
  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
  end
  .
  .
  .
end

ここで、following_idsはralationshipsテーブルからfollower_idが自身のuser_idであるようなデータのfollowed_idの集合、つまり自分がフォローしているユーザーのidの集合であり、それをMicropostモデルのwhereメソッド内でuser_id INに渡し、フォローしているユーザーのマイクロポストを取得している。