LoginSignup
0
0

More than 1 year has passed since last update.

railsチュートリアル第十四章 ステータスフィールド サブセレクト

Posted at

ステータスフィールド

現在のユーザーにフォローされているユーザーのマイクロポストの配列を作成し、現在のユーザー自身のマイクロポストと合わせて表示します。
このセクションを通して、複雑さを増したフィードの実装に進んでいきます。
これを実現するためには、RailsとRubyの高度な機能の他に、SQLプログラミングの技術も必要です。

動機と計画

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

test/models/user_test.rb

require 'test_helper'
.
.
.
  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

テスト

ubuntu:~/environment/sample_app (following-users) $ rails t
Running via Spring preloader in process 5728
Started with run options --seed 13331

 FAIL["test_feed_should_have_the_right_posts", #<Minitest::Reporters::Suite:0x000056391fee5aa8 @name="UserTest">, 3.5545889589998296]
 test_feed_should_have_the_right_posts#UserTest (3.56s)
        Expected false to be truthy.
        test/models/user_test.rb:131:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:129:in `block in <class:UserTest>'

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

Finished in 4.55511s
74 tests, 341 assertions, 1 failures, 0 errors, 0 skips

Expected false to be truthy.

とりあえず動くフィードの実装

app/models/user.rb


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

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

Finished in 4.11729s
74 tests, 378 assertions, 0 failures, 0 errors, 0 skips

演習

1.
リスト 14.44において、現在のユーザー自身の投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか?

2.
リスト 14.44において、フォローしているユーザーの投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか?

3.
リスト 14.44において、フォローしていないユーザーの投稿を含めるためにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか? ヒント: 自分自身とフォローしているユーザー、そしてそれ以外という集合は、いったいどういった集合を表すのか考えてみてください。

サブセレクト

whereメソッド内の変数に、キーと値のペアを使う

app/models/user.rb

class User < ApplicationRecord
.
.
.
  # 試作feedの定義
  # 完全な実装は次章の「ユーザーをフォローする」を参照
  def feed
  # すべてのユーザーがフィードを持つので、feedメソッドはUserモデルで作るのが自然です
  Micropost.where("user_id IN (:following_ids) OR user_id = :user_id",
    following_ids: following_ids, user_id: id)    # following_ids フォローのユーザーidを取得
    # id 要素
    # whereメソッド テーブル内の条件に一致したレコードを配列の形で取得することができるメソッド
    # user_idを条件として取得することができる。
    # 上の疑問符があることで、SQLクエリに代入する前にidがエスケープされるため
    #   、SQLインジェクションと呼ばれる深刻なセキュリティホールを避けることができます。
    # SQL文に変数を代入する場合は常にエスケープする習慣をぜひ身につけてください。
  end
.
.
.
end

フィードの最終的な実装

app/models/user.rb

class User < ApplicationRecord
.
.
.
  # 試作feedの定義
  # 完全な実装は次章の「ユーザーをフォローする」を参照
  def feed
  # すべてのユーザーがフィードを持つので、feedメソッドはUserモデルで作るのが自然です
    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)    
    # following_ids フォローのユーザーidを取得
    # id 要素
    # whereメソッド テーブル内の条件に一致したレコードを配列の形で取得することができるメソッド
    # user_idを条件として取得することができる。
    # 上の疑問符があることで、SQLクエリに代入する前にidがエスケープされるため
    #   、SQLインジェクションと呼ばれる深刻なセキュリティホールを避けることができます。
    # SQL文に変数を代入する場合は常にエスケープする習慣をぜひ身につけてください。
  end
.
.
.
end
テスト
ubuntu:~/environment/sample_app (following-users) $ rails t
Running via Spring preloader in process 10510
Started with run options --seed 15480

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

Finished in 4.25870s
74 tests, 378 assertions, 0 failures, 0 errors, 0 skips
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0