Open saran12345678 opened 2 months ago
irb(main):003> User.first.active_relationships.create(followed_id: User.second.id)
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 1]]
TRANSACTION (0.0ms) begin transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Relationship Create (0.4ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 1], ["followed_id", 2], ["created_at", "2024-09-05 12:12:00.773049"], ["updated_at", "2024-09-05 12:12:00.773049"]]
TRANSACTION (30.5ms) commit transaction
=> #<Relationship:0x000076f5624f28a0 id: 1, follower_id: 1, followed_id: 2, created_at: Thu, 05 Sep 2024 12:12:00.773049000 UTC +00:00, updated_at: Thu, 05 Sep 2024 12:12:00.773049000 UTC +00:00>
ID1がID2をフォローしているとわかる
irb(main):009> User.first.active_relationships
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
Relationship Load (0.1ms) SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=> [#<Relationship:0x000076f561a0a780 id: 1, follower_id: 1, followed_id: 2, created_at: Thu, 05 Sep 2024 12:12:00.773049000 UTC +00:00, updated_at: Thu, 05 Sep 2024 12:12:00.773049000 UTC +00:00>]
validatesをコメントアウトした状態で、テストに成功することを確認
class Relationship < ApplicationRecord
# belongs_to :follower, class_name: "User"
# belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
end
95 runs, 359 assertions, 0 failures, 0 errors, 0 skips
エラーになるため、firstとsecondを使用した
irb(main):005> michael = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=>
#<User:0x00007ee16818ce50
...
irb(main):006> archer = User.second
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ? [["LIMIT", 1], ["OFFSET", 1]]
=>
#<User:0x00007ee16805d840
...
irb(main):011> michael.follow(archer)
TRANSACTION (0.1ms) begin transaction
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
Relationship Create (0.3ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 1], ["followed_id", 2], ["created_at", "2024-09-05 12:51:27.654311"], ["updated_at", "2024-09-05 12:51:27.654311"]]
TRANSACTION (25.6ms) commit transaction
User Load (0.1ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=>
[#<User:0x00007ee16805d840
id: 2,
name: "Zula Goodwin",
email: "example-1@railstutorial.org",
created_at: Thu, 05 Sep 2024 07:48:18.581206000 UTC +00:00,
updated_at: Thu, 05 Sep 2024 07:48:18.581206000 UTC +00:00,
password_digest: "[FILTERED]",
remember_digest: nil,
admin: false,
activation_digest: "$2a$12$5Ldvj.V4yWA5m46e1kwC6uK3tNX6hTO2Vbr87G5q6Zq3DRGoTh8ae",
activated: true,
activated_at: Thu, 05 Sep 2024 07:48:18.351068000 UTC +00:00,
reset_digest: nil,
reset_sent_at: nil>]
irb(main):013> michael.following?(archer)
=> true
irb(main):014> michael.unfollow(archer)
TRANSACTION (0.1ms) begin transaction
Relationship Delete All (0.4ms) DELETE FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? [["follower_id", 1], ["followed_id", 2]]
TRANSACTION (26.0ms) commit transaction
=>
[#<User:0x00007ee16805d840
id: 2,
name: "Zula Goodwin",
email: "example-1@railstutorial.org",
created_at: Thu, 05 Sep 2024 07:48:18.581206000 UTC +00:00,
updated_at: Thu, 05 Sep 2024 07:48:18.581206000 UTC +00:00,
password_digest: "[FILTERED]",
remember_digest: nil,
admin: false,
activation_digest: "$2a$12$5Ldvj.V4yWA5m46e1kwC6uK3tNX6hTO2Vbr87G5q6Zq3DRGoTh8ae",
activated: true,
activated_at: Thu, 05 Sep 2024 07:48:18.351068000 UTC +00:00,
reset_digest: nil,
reset_sent_at: nil>]
irb(main):015> michael.following?(archer)
=> false
irb(main):016> michael.follow(michael)
=> nil
irb(main):017> michael.following?(michael)
=> false
followではInsert unfollowではdelete それ以外ではSelect文が実行されている
irb(main):007> user1.followers.map(&:id)
User Load (0.2ms) SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> [2, 3]
一致していることを確認
irb(main):008> user1.followers.count
User Count (0.2ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> 2
SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
user.followers.to_a.countとの違いはない。
期待される結果と一致している
irb(main):001> User.first.followers.count
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
User Count (0.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]]
=> 38
一致している
irb(main):002> User.first.following.count
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
User Count (0.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? [["follower_id", 1]]
=> 49
user2の場合はSeedのデータを見る限りフォローしていないため、フォローボタンが表示される user5の場合は、同じくSeedのデータにてフォローが行われているため、アンフォローボタンが表示される user1の場合は、current_userが@userではないかの分岐があるため、ボタンは非表示になるように実装されている
正しく数値が表示されている
to_sにて文字列に変換しないとテストに失敗する
assert_match @user.followers.count.to_s, response.body
assert_match @user.following.count.to_s, response.body
サイドバーの画像リンクが機能していることも確認
2箇所コメントアウト 1箇所ではアイコン下もしくはフォロー(フォロワー)一覧のリンクが残るため、テストに成功してしまう。
<% provide(:title, @title) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= gravatar_for @user %>
<h1><%= @user.name %></h1>
<span><%= link_to "view my profile", @user %></span>
<span><strong>Microposts:</strong> <%= @user.microposts.count %></span>
</section>
<section class="stats">
<%= render 'shared/stats' %>
<% if @users.any? %>
<div class="user_avatars">
<% @users.each do |user| %>
<%# <%= link_to gravatar_for(user, size: 30), user %> %>
<% end %>
</div>
<% end %>
</section>
</aside>
<div class="col-md-8">
<h3><%= @title %></h3>
<% if @users.any? %>
<ul class="users follow">
<%# <%= render @users %> %>
</ul>
<%= will_paginate %>
<% end %>
</div>
</div>
1) Failure:
FollowPagesTest#test_following_page [/workspaces/sample_app/test/integration/following_test.rb:19]:
Expected at least 1 element matching "a[href="/users/409608538"]", found 0..
Expected 0 to be >= 1.
2) Failure:
FollowPagesTest#test_followers_page [/workspaces/sample_app/test/integration/following_test.rb:29]:
Expected at least 1 element matching "a[href="/users/409608538"]", found 0..
Expected 0 to be >= 1.
100 runs, 380 assertions, 2 failures, 0 errors, 0 skips
フォロー時
Relationship Create (3.6ms) INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["follower_id", 1], ["followed_id", 2], ["created_at", "2024-09-05 23:12:22.526405"], ["updated_at", "2024-09-05 23:12:22.526405"]]
アンフォロー時
Relationship Delete All (0.3ms) DELETE FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? [["follower_id", 1], ["followed_id", 2]]
createアクションのformat.htmlのみをコメントアウト
1) Error:
FollowTest#test_should_follow_a_user_the_standard_way:
ActionController::UnknownFormat: ActionController::UnknownFormat
app/controllers/relationships_controller.rb:7:in `create'
test/integration/following_test.rb:39:in `block (2 levels) in <class:FollowTest>'
test/integration/following_test.rb:38:in `block in <class:FollowTest>'
106 runs, 392 assertions, 0 failures, 1 errors, 0 skips
createアクションのformat.turbo_streamのみをコメントアウト
1) Error:
FollowTest#test_should_follow_a_user_with_Hotwire:
ActionController::UnknownFormat: ActionController::UnknownFormat
app/controllers/relationships_controller.rb:7:in `create'
test/integration/following_test.rb:46:in `block (2 levels) in <class:FollowTest>'
test/integration/following_test.rb:45:in `block in <class:FollowTest>'
106 runs, 394 assertions, 0 failures, 1 errors, 0 skips
destroyアクションのformat.htmlのみをコメントアウト
1) Error:
UnfollowTest#test_should_unfollow_a_user_the_standard_way:
ActionController::UnknownFormat: ActionController::UnknownFormat
app/controllers/relationships_controller.rb:16:in `destroy'
test/integration/following_test.rb:65:in `block (2 levels) in <class:UnfollowTest>'
test/integration/following_test.rb:64:in `block in <class:UnfollowTest>'
106 runs, 391 assertions, 0 failures, 1 errors, 0 skips
destroyアクションのformat.turbo_streamのみをコメントアウト
1) Error:
UnfollowTest#test_should_unfollow_a_user_with_Hotwire:
ActionController::UnknownFormat: ActionController::UnknownFormat
app/controllers/relationships_controller.rb:16:in `destroy'
test/integration/following_test.rb:73:in `block (2 levels) in <class:UnfollowTest>'
test/integration/following_test.rb:72:in `block in <class:UnfollowTest>'
106 runs, 394 assertions, 0 failures, 1 errors, 0 skips
IDが大きいほど最新であるため、IDの降順で取得されるはずである。 これはマイクロポストの際にも同様であったためそのように定義する。 user.feed.map(&:id)ではIDを取得しようとしているため、図14.22を参考にすると、 10,9,7,5,4,2,1の順で取得できるはずである。
OR user_id = ?", following_ids, idを取り除けばフォローしている人の投稿のみが表示されるはず
# ユーザーのステータスフィードを返す
def feed
Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
end
このテストが失敗するはず
# フォロワーがいるユーザー自身の投稿を確認
michael.microposts.each do |post_self|
assert michael.feed.include?(post_self)
end
失敗することを確認
4) Failure:
UserTest#test_feed_should_have_the_right_posts [/workspaces/sample_app/test/models/user_test.rb:111]:
Expected false to be truthy.
user_id IN (?) OR の条件を取り除けば良い
Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
Micropost.whereを使用しなければ、Where句の条件が指定されてなくなるため全件表示される。
Micropost.all
test "feed on Home page" do
get root_path
@user.feed.paginate(page: 1).each do |micropost|
assert_match CGI.escapeHTML(micropost.content), response.body
end
CGI.escapeHTMLを行わないとテストに失敗する。 test/fixtures/microposts.ymlのテストデータ
"I'm sorry. Your words made sense, but your sarcastic tone did not."
テスト失敗時のエラー文抜粋
/I'm\ sorry\.\ Your\ words\ made\ sense,\ but\ your\ sarcastic\ tone\ did\ not\.
演習にて「「sorry」を検索すると、原因の究明に役立つでしょう。」とあることから、 シングルクォーテーションがエスケープされているため、assert_matchに失敗していると思う。
test/fixtures/microposts.ymlにてシングルクォーテーションを全て取り除いた上で、 再度テストを実施すると、テストに成功するため合っていると判断
@saran12345678 ➜ /workspaces/sample_app (main) $ rails db:seed
@saran12345678 ➜ /workspaces/sample_app (main) $ rails t
Run options: --seed 11162
# Running:
............................................................................................................
Finished in 7.006843s, 15.4135 runs/s, 70.2171 assertions/s.
このコードが返すフィードがテストでパスすることを確かめてみましょう。
108 runs, 492 assertions, 0 failures, 0 errors, 0 skips
次はリスト 14.51のテストを使ってこのエラーをキャッチしてください。 下記テストを追加
assert_equal michael.feed.distinct, michael.feed
テストが失敗し、重複をキャッチできていることを確認
108 runs, 458 assertions, 1 failures, 0 errors, 0 skips
エラーをキャッチできたら、クエリにdistinctメソッドを追加したコード(リスト 14.52)に置き換えるとテストが green になることを確かめてください。 distinctを追加することでテストに成功するようになった
108 runs, 528 assertions, 0 failures, 0 errors, 0 skips
コンソールにて、feed実行時にDISTINCTが使用されていることを確認
Micropost Count (3.5ms) SELECT COUNT(DISTINCT "microposts"."id") FROM "microposts" LEFT OUTER JOIN "users" ON "users"."id" = "microposts"."user_id" LEFT OUTER JOIN "relationships" ON "relationships"."followed_id" = "users"."id" LEFT OUTER JOIN "users" "followers_users" ON "followers_users"."id" = "relationships"."follower_id" WHERE (relationships.follower_id = 1 or microposts.user_id = 1)
↳ app/views/shared/_feed.html.erb:1
Micropost Load (1.3ms) SELECT DISTINCT "microposts".* FROM "microposts" LEFT OUTER JOIN "users" ON "users"."id" = "microposts"."user_id" LEFT OUTER JOIN "relationships" ON "relationships"."followed_id" = "users"."id" LEFT OUTER JOIN "users" "followers_users" ON "followers_users"."id" = "relationships"."follower_id" WHERE (relationships.follower_id = 1 or microposts.user_id = 1) ORDER BY "microposts"."created_at" DESC LIMIT ? OFFSET ? [["LIMIT", 30], ["OFFSET", 0]]
↳ app/views/shared/_feed.html.erb:3
図 14.7のid=1のユーザーに対してuser.following.map(&:id)を実行すると、結果はどのようになるでしょうか? 想像してみてください。(ヒント: 4.3.2で紹介したmap(&:method_name)のパターンを思い出してください。例えばuser.following.map(&:id)の場合、idの配列を返します。)
ID:1がフォローしているユーザのID一覧が出力される
図 14.7を参考にして、id=2のユーザーに対してuser.followingを実行すると、結果はどのようになるでしょうか? 想像してみてください。また、同じユーザーに対してuser.following.map(&:id)を実行すると、結果はどのようになるでしょうか? 想像してみてください。
IDが1のユーザ情報を出力する 1が出力される ※ユーザID:2をフォローしているのはID:1のみであるため