LoginSignup
0
0

More than 1 year has passed since last update.

railsチュートリアル第十四章 フォローしているユーザー

Posted at

フォローしているユーザー

Userモデルにfollowingの関連付けを追加する

app/models/user.rb

class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  # 他のモデルとの間に「1対多」のつながり
  # has_many関連付けが使われている場合、
  #   「反対側」のモデルでは多くの場合belongs_toが使われます。
  # dependent: :destroy
  # ユーザーが破棄された場合
  #   、ユーザーのマイクロポストも同様に破棄される。
  has_many :active_relationships, class_name:  "Relationship",
  # :active_relationsshitpsデータモデル 能動的関係(フォローしているがフォローはされていない関係)
  # class_name: テーブル名 "Relationship"
                                  foreign_key: "follower_id",
                                  # foreign_key: 外部キー
                                  #   データベースの二つのテーブルを繋げる
                                  # Micropostモデルとrelationshipsモデルを繋げる
                                  dependent:   :destroy
                                  # ユーザーが削除されるとマイクロポストも削除される
  has_many :following, through: :active_relationships, source: :followed
  # :following followingデータモデル 
  # has_many :through関連付けは、他方のモデルと「多対多」のつながりを設定する場合によく使われます。
  # この関連付けは、2つのモデルの間に「第3のモデル」(joinモデル)が介在する点が特徴です。
  # フォローするには:active_relationshipsデータモデルが介在する
  # source: following配列の元はfollowed idの集合である
.
.
.
end

“following” 関連のメソッドをテストする

test/models/user_test.rb

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end
.
.
.
  test "should follow and unfollow a user" do
    michael = users(:michael)
    # テストユーザーを代入
    archer  = users(:archer)
    assert_not michael.following?(archer)
    # archerはmichaelをふぉろーしていないことを確認
    michael.follow(archer)
    # archerをフォロー
    assert michael.following?(archer)
    # フォローしているか?
    michael.unfollow(archer)
    assert_not michael.following?(archer)
  end
end

"following" 関連のメソッド

app/models/user.rb

class User < ApplicationRecord
.
.
.
   # ユーザーをフォローする
  def follow(other_user)
    following << other_user
    # followingは配列になっている
    # << 指定された obj を自身の末尾に破壊的に追加します。
    # following配列にothe_userを破壊的に追加させる
  end

  # ユーザーをフォロー解除する
  def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
    # active_relationshiipsデータモデルからフォロワーをidを探す
    # それを削除する
  end

  # 現在のユーザーがフォローしてたらtrueを返す
  def following?(other_user)
    following.include?(other_user)
    # followingデータモデル
    # 引数(othe r_user)を配列の名から探す
    # それがあればtureを返す。
  end

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

  63/63: [=============================] 100% Time: 00:00:07, Time: 00:00:07

Finished in 7.01682s
63 tests, 319 assertions, 0 failures, 0 errors, 0 skips

演習

1.コンソールを開き、リスト 14.9のコードを順々に実行してみましょう。

>> michael.follow(archer)
   (0.1ms)  begin transaction
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Relationship Create (1.6ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 1], ["followed_id", 2], ["created_at", "2021-10-28 12:59:26.258244"], ["updated_at", "2021-10-28 12:59:26.258244"]]
   (0.1ms)  rollback transaction
Traceback (most recent call last):
        3: from (irb):5
        2: from (irb):5:in `rescue in irb_binding'
        1: from app/models/user.rb:135:in `follow'
ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: relationships.follower_id, relationships.followed_id)
>> michael.following?(archer)
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ?  [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> true

>> michael.follow(archer)
   (0.1ms)  begin transaction
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Relationship Create (0.6ms)  INSERT INTO "relationships" ("follower_id", "followed_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["follower_id", 1], ["followed_id", 2], ["created_at", "2021-10-28 13:00:30.403974"], ["updated_at", "2021-10-28 13:00:30.403974"]]
   (0.1ms)  rollback transaction
Traceback (most recent call last):
        2: from (irb):7
        1: from app/models/user.rb:135:in `follow'
ActiveRecord::RecordNotUnique (SQLite3::ConstraintException: UNIQUE constraint failed: relationships.follower_id, relationships.followed_id)
# 一意性がないらしい 

>> michael.following?(archer)
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ?  [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> true

>> michael.unfollow(archer)
  Relationship Load (0.2ms)  SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ?  [["follower_id", 1], ["followed_id", 2], ["LIMIT", 1]]
   (0.0ms)  begin transaction
  Relationship Destroy (6.1ms)  DELETE FROM "relationships" WHERE "relationships"."id" = ?  [["id", 1]]
   (7.7ms)  commit transaction
=> #<Relationship id: 1, follower_id: 1, followed_id: 2, created_at: "2021-10-28 06:05:06", updated_at: "2021-10-28 06:05:06">

>> michael.following?(archer)
  User Exists? (0.2ms)  SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ?  [["follower_id", 1], ["id", 2], ["LIMIT", 1]]
=> false

2.先ほどの演習の各コマンド実行時の結果を見返してみて、実際にはどんなSQLが出力されたのか確認してみましょう。

SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ? 

 SELECT "relationships".* FROM "relationships" WHERE "relationships"."follower_id" = ? AND "relationships"."followed_id" = ? LIMIT ? 

 SELECT 1 AS one FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? AND "users"."id" = ? LIMIT ? 

わからない。

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