Komei22 / rails-tutorial

rails-tutorialのsample_app作っていきます
0 stars 0 forks source link

ch14.1.5 #98

Closed Komei22 closed 7 years ago

Komei22 commented 7 years ago

演習1

コンソールを開き、何人かのユーザーが最初のユーザーをフォローしている状況を作ってみてください。最初のユーザーをuserとすると、user.followers.map(&:id)の値はどのようになっているでしょうか?

irb(main):001:0> user1 = User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-07-11 09:36:31", updated_at: "2017-07-11 09:36:31", password_digest: "$2a$10$OtC8TkXqecT1WakY8FRpXu.xccuvXG/Yg0qON9MXf4J...", remember_digest: nil, admin: true, activation_digest: "$2a$10$giMTzAH0Yk.pV1RsWuQ0WOHIYEzQcI59tRxPKn96zDl...", activated: true, activated_at: "2017-07-11 09:36:30", reset_digest: nil, reset_sent_at: nil>
irb(main):002:0> user2 = User.second
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ?  [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Meaghan Denesik", email: "example-1@railstutorial.org", created_at: "2017-07-11 09:36:31", updated_at: "2017-07-11 09:36:31", password_digest: "$2a$10$Wi3RpNlOlZEi8hJ4Q099H.ZZgybvyZnVuYy.82xb6p9...", remember_digest: nil, admin: false, activation_digest: "$2a$10$q8figxvxn.IxEJxdirPpFO/ugXTPd/RtNy1f.XfOp8W...", activated: true, activated_at: "2017-07-11 09:36:31", reset_digest: nil, reset_sent_at: nil>
irb(main):003:0> user3 = User.third
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ?  [["LIMIT", 1], ["OFFSET", 2]]
=> #<User id: 3, name: "Loraine Hilll V", email: "example-2@railstutorial.org", created_at: "2017-07-11 09:36:31", updated_at: "2017-07-11 09:36:31", password_digest: "$2a$10$wZiMOjhVxF1Zea1L5kN0U.FhMuzN4cDH/mUjUj9ch9N...", remember_digest: nil, admin: false, activation_digest: "$2a$10$TayfP6db3MeHj1sjQL8GrOlZztf43RDOTBShbpCKAJ2...", activated: true, activated_at: "2017-07-11 09:36:31", reset_digest: nil, reset_sent_at: nil>
irb(main):004:0> user2.follow(user1)
   (0.1ms)  begin transaction
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  SQL (0.4ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 2], ["followed_id", 1], ["created_at", "2017-07-14 03:31:31.460386"], ["updated_at", "2017-07-14 03:31:31.460386"]]
   (2.6ms)  commit transaction
=> #<Relationship id: 4, follower_id: 2, followed_id: 1, created_at: "2017-07-14 03:31:31", updated_at: "2017-07-14 03:31:31">
irb(main):005:0> user3.follow(user1)
   (0.1ms)  begin transaction
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  SQL (0.4ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 3], ["followed_id", 1], ["created_at", "2017-07-14 03:31:38.508039"], ["updated_at", "2017-07-14 03:31:38.508039"]]
   (2.7ms)  commit transaction
=> #<Relationship id: 5, follower_id: 3, followed_id: 1, created_at: "2017-07-14 03:31:38", updated_at: "2017-07-14 03:31:38">
irb(main):006:0> user1.followers.map(&:id)
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ?  [["followed_id", 1]]
=> [2, 3]

演習2

上の演習が終わったら、user.followers.countの実行結果が、先ほどフォローさせたユーザー数と一致していることを確認してみましょう。

irb(main):007:0> user1.followers.count
   (0.3ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ?  [["followed_id", 1]]
=> 2

演習3

user.followers.countを実行した結果、出力されるSQL文はどのような内容になっているでしょうか? また、user.followers.to_a.countの実行結果と違っている箇所はありますか? ヒント: もしuserに100万人のフォロワーがいた場合、どのような違いがあるでしょうか? 考えてみてください。

irb(main):007:0> user1.followers.count
   (0.3ms)  SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ?  [["followed_id", 1]]
=> 2
irb(main):008:0> user1.followers.to_a.count
=> 2

user1.followers.countはデータベース上でfollowed_idが1の数をカウントしている user1.followers.to_a.countは配列に変換した後プログラム上でカウントしている 100万人のユーザにフォローされていた場合、データベース上で検索する方が高速に処理が可能なため、速度に大きな差が生まれてくると考えられる