neutral2010 / log

作業用のissueを立てるためのリポジトリ
0 stars 0 forks source link

「Railsでユーザーフォローを作る」 #5

Open neutral2010 opened 2 years ago

neutral2010 commented 2 years ago

参考にしたもの

Web

neutral2010 commented 2 years ago

model作成・削除・コミット取り消し記録

~/fBootcamp/fjord-books_app my-follow_users*
❯ rails g model Follow_following follower_id:integer followed_id:integer
Running via Spring preloader in process 82202
      invoke  active_record
      create    db/migrate/20220410150944_create_follow_followings.rb
      create    app/models/follow_following.rb
      invoke    test_unit
      create      test/models/follow_following_test.rb
      create      test/fixtures/follow_followings.yml

~/fBootcamp/fjord-books_app my-follow_users*
❯ rails db:migrate                                                      
== 20220410150944 CreateFollowFollowings: migrating ===========================
-- create_table(:follow_followings)
   -> 0.0025s
-- add_index(:follow_followings, :follower_id)
   -> 0.0010s
-- add_index(:follow_followings, :followed_id)
   -> 0.0010s
-- add_index(:follow_followings, [:follower_id, :followed_id], {:unique=>true})
   -> 0.0023s
== 20220410150944 CreateFollowFollowings: migrated (0.0078s) ==================

その後、このモデルは削除

~/fBootcamp/fjord-books_app my-follow_users
❯ rails d model Follow_following follower_id:integer followed_id:integer
Running via Spring preloader in process 9405
      invoke  active_record
      remove    db/migrate/20220410150944_create_follow_followings.rb
      remove    app/models/follow_following.rb
      invoke    test_unit
      remove      test/models/follow_following_test.rb
      remove      test/fixtures/follow_followings.yml

モデル作成のコミット(直線)を削除したい → git reset --hard fbecbf02001d0f00f482e0b3eca99ae96f9d7b88 また削除したモデルがができてしまっている! → 直線のコミットを取り消すコマンド git reset --hard HEAD~ 無事にコミット取り消し完了! → その後にモデルを削除するコマンドでやりたいこと成功!

~/fBootcamp/fjord-books_app my-follow_users*
❯ git log
commit fbecbf02001d0f00f482e0b3eca99ae96f9d7b88 (HEAD -> my-follow_users)
Author: neutral2010 <kasiwamoti5@gmail.com>
Date:   Mon Apr 11 00:13:01 2022 +0900

    rails g model Follow_following follower_id:integer followed_id:integer

    インデックス追加・組み合わせをユニークにする機能を実装

commit 41eba1156dbbfc4dec9de906b2985d060a8ce1fe (origin/07-follow_users, 07-follow_users)
Merge: ba999c0 ab65ff4

~/fBootcamp/fjord-books_app my-follow_users* 12s
❯ git reset --hard fbecbf02001d0f00f482e0b3eca99ae96f9d7b88
HEAD is now at fbecbf0 rails g model Follow_following follower_id:integer followed_id:integer

~/fBootcamp/fjord-books_app my-follow_users
❯ git log                                                  
commit fbecbf02001d0f00f482e0b3eca99ae96f9d7b88 (HEAD -> my-follow_users)
Author: neutral2010 <kasiwamoti5@gmail.com>
Date:   Mon Apr 11 00:13:01 2022 +0900

    rails g model Follow_following follower_id:integer followed_id:integer

    インデックス追加・組み合わせをユニークにする機能を実装

commit 41eba1156dbbfc4dec9de906b2985d060a8ce1fe (origin/07-follow_users, 07-follow_users)
Merge: ba999c0 ab65ff4

~/fBootcamp/fjord-books_app my-follow_users 45s
❯ git status
On branch my-follow_users
nothing to commit, working tree clean

~/fBootcamp/fjord-books_app my-follow_users
❯ tig

~/fBootcamp/fjord-books_app my-follow_users 2m 10s
❯ git reset --hard HEAD~
HEAD is now at 41eba11 Merge branch '06-user_icon' into 07-follow_users

~/fBootcamp/fjord-books_app my-follow_users
❯ tig

~/fBootcamp/fjord-books_app my-follow_users 21s
❯ rails d model Follow_following follower_id:integer followed_id:integer
Running via Spring preloader in process 10415
      invoke  active_record
      remove    db/migrate/20220415234850_create_follow_followings.rb
      remove    app/models/follow_following.rb
      invoke    test_unit
      remove      test/models/follow_following_test.rb
      remove      test/fixtures/follow_followings.yml
neutral2010 commented 2 years ago

手順の整理① 中間テーブルの設計と作成

多対多を実現するための中間テーブルにふさわしい名前

以前設計のプラクティス(Twitter)の時の名前を使うことに。ER図ではfollow_relations これをRailsの命名規則Active Record の基礎 - Railsガイド 2-1 命名ルール 、に従うと、、、

データベースのテーブル名を探索するときに、モデルのクラス名を複数形にした名前で探索します。つまり、Bookというモデルクラスがある場合、これに対応するデータベースのテーブルは複数形の「books」になります。

モデルのクラス名が2語以上の複合語である場合、Rubyの慣習であるキャメルケース(CamelCaseのように語頭を大文字にしてスペースなしでつなぐ)に従ってください。一方、テーブル名はスネークケース(snake_caseなど、小文字とアンダースコアで構成する)にしなければなりません。

image

(Railsガイドより)

カラムの型・制約・インデックス(DBテーブルの設計)

作成するカラム

references型にすると起こること

bin/rails generate migration FollowRelation user:referencesすると

今回は、結局全部書き換えないといけなくなるので、integerで指定するのでは。

制約・バリデーション

両方に、完全でないところができてしまわないよう、、、

結論、以下の3点を記述することが理想形となります。 フォームに「required: true」 モデルに「presence: true」 テーブルに「null: false」 「required :true」を使用することで、空文字での送信を防ぐことができます。

作成(コード)

モデル作成コマンド

~/fBootcamp/fjord-books_app my-follow_users
❯ rails g model FollowRelation follower_id:integer followed_id:integer
Running via Spring preloader in process 26241
      invoke  active_record
      create    db/migrate/20220418040546_create_follow_relations.rb
      create    app/models/follow_relation.rb
      invoke    test_unit
      create      test/models/follow_relation_test.rb
      create      test/fixtures/follow_relations.yml

マイグレーションファイル編集

元のファイル

class CreateFollowRelations < ActiveRecord::Migration[6.1]
  def change
    create_table :follow_relations do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
  end
end

変更後

class CreateFollowRelations < ActiveRecord::Migration[6.1]
  def change
    create_table :follow_relations do |t|
      t.integer :follower_id, null: false #Not Null制約
      t.integer :followed_id, null: false

      t.timestamps
    end
    # follower_idとfollowed_idで頻繁に検索することになるのでインデックス追加
    add_index :follow_relations, :follower_id
    add_index :follow_relations, :followed_id
    # 組み合わせが必ずユニークであることを保証する仕組み
    # あるユーザーが同じユーザーを2回以上フォローすることを防ぐ
    add_index :follow_relations, [:follower_id, :followed_id], unique: true
  end
end
neutral2010 commented 2 years ago

手順の整理② FollowRelationモデルに関する実装

バリデーション

  validates :follower_id, presence: true
  validates :followed_id, presence: true

関連付け

使えるようになったメソッド

メソッド 意味
active_relationship.follower フォロワーを返します
active_relationship.followed フォローしているユーザーを返します
user.active_relationships.create(followed_id: other_user.id) userと紐付けて能動的関係を作成/登録する
user.active_relationships.create!(followed_id: other_user.id) userを紐付けて能動的関係を作成/登録する(失敗時にエラーを出力)
user.active_relationships.build(followed_id: other_user.id) userと紐付けた新しいRelationshipオブジェクトを返す

分かったこと

neutral2010 commented 2 years ago

手順の整理③ Userモデルにメソッド作成

neutral2010 commented 2 years ago

手順の整理④ 中間テーブルのコントローラー作成とメソッド作成

rails g controller follow_relations
Running via Spring preloader in process 77201
      create  app/controllers/follow_relations_controller.rb
      invoke  erb
      create    app/views/follow_relations
      invoke  test_unit
      create    test/controllers/follow_relations_controller_test.rb
      invoke  helper
      create    app/helpers/follow_relations_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/follow_relations.scss
neutral2010 commented 2 years ago

手順の整理⑤ ルーティング設定

resources :follow_relations, only: %i(create destroy) https://railstutorial.jp/chapters/user_microposts?version=6.0#code-microposts_resource 参照

neutral2010 commented 2 years ago

手順の整理⑥ viewの編集

neutral2010 commented 2 years ago

分からなくて気になっていること

neutral2010 commented 2 years ago

フォロー解除ボタンの機能にエラー


Started GET "/users/51/followers" for ::1 at 2022-04-26 08:37:08 +0900
Processing by UsersController#followers as HTML
  Parameters: {"id"=>"51"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 51], ["LIMIT", 1]]
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 51], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:29:in `set_user'
  Rendering layout layouts/application.html.erb
  Rendering users/followers.html.erb within layouts/application
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ?  [["follower_id", 51]]
  ↳ app/views/users/followers.html.erb:12
  ActiveStorage::Attachment Load (0.3ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.3ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 2], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 3], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.3ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 5], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 10], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 14], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.8ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 19], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 20], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 25], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/followers.html.erb:17
  Rendered users/followers.html.erb within layouts/application (Duration: 90.2ms | Allocations: 11684)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered layout layouts/application.html.erb (Duration: 102.5ms | Allocations: 15451)
Completed 200 OK in 124ms (Views: 100.7ms | ActiveRecord: 3.1ms | Allocations: 17756)

Started GET "/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDVG9JYTJWNVNTSWhhbUZ2ZERCdU5HcHNjR1l3Wm10eE9Xb3hkWEJpY25WbWFXRTNlQVk2QmtWVU9oQmthWE53YjNOcGRHbHZia2tpUTJsdWJHbHVaVHNnWm1sc1pXNWhiV1U5SWtsTlIxODJNelEyTG1wd1p5STdJR1pwYkdWdVlXMWxLajFWVkVZdE9DY25TVTFIWHpZek5EWXVhbkJuQmpzR1ZEb1JZMjl1ZEdWdWRGOTBlWEJsU1NJUGFXMWhaMlV2YW5CbFp3WTdCbFE2RVhObGNuWnBZMlZmYm1GdFpUb0tiRzlqWVd3PSIsImV4cCI6IjIwMjItMDQtMjVUMjM6NDI6MDQuNzQyWiIsInB1ciI6ImJsb2Jfa2V5In19--f2c878c14c00976f664765d91713e76926916084/IMG_6346.jpg" for ::1 at 2022-04-26 08:37:08 +0900
Processing by ActiveStorage::DiskController#show as JPEG
  Parameters: {"encoded_key"=>"[FILTERED]", "filename"=>"IMG_6346"}
Completed 200 OK in 1ms (ActiveRecord: 0.0ms | Allocations: 319)

Started GET "/users/1" for ::1 at 2022-04-26 08:37:50 +0900
Processing by UsersController#show as HTML
  Parameters: {"id"=>"1"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 51], ["LIMIT", 1]]
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:29:in `set_user'
  Rendering layout layouts/application.html.erb
  Rendering users/show.html.erb within layouts/application
   (0.3ms)  SELECT COUNT(*) FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ?  [["follower_id", 1]]
  ↳ app/views/users/show.html.erb:9
   (0.2ms)  SELECT COUNT(*) FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."follower_id" WHERE "follow_relations"."followed_id" = ?  [["followed_id", 1]]
  ↳ app/views/users/show.html.erb:10
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/show.html.erb:35
  User Exists? (0.9ms)  SELECT 1 AS one FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ? AND "users"."id" = ? LIMIT ?  [["follower_id", 51], ["id", 1], ["LIMIT", 1]]
  ↳ app/models/user.rb:28:in `following?'
  FollowRelation Load (0.1ms)  SELECT "follow_relations".* FROM "follow_relations" WHERE "follow_relations"."follower_id" = ? AND "follow_relations"."followed_id" = ? LIMIT ?  [["follower_id", 51], ["followed_id", 1], ["LIMIT", 1]]
  ↳ app/views/users/show.html.erb:43
  Rendered users/show.html.erb within layouts/application (Duration: 31.2ms | Allocations: 5870)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered layout layouts/application.html.erb (Duration: 53.9ms | Allocations: 9602)
Completed 200 OK in 64ms (Views: 53.2ms | ActiveRecord: 2.2ms | Allocations: 11721)

Started DELETE "/follow_relations/17" for ::1 at 2022-04-26 08:40:16 +0900
Processing by FollowRelationsController#destroy as HTML
  Parameters: {"authenticity_token"=>"[FILTERED]", "followed_id"=>"1", "commit"=>"フォローを解除する", "id"=>"17"}
  User Load (0.1ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 51], ["LIMIT", 1]]
  FollowRelation Load (0.1ms)  SELECT "follow_relations".* FROM "follow_relations" WHERE "follow_relations"."follower_id" = ? AND "follow_relations"."followed_id" = ? LIMIT ?  [["follower_id", 51], ["followed_id", 17], ["LIMIT", 1]]
  ↳ app/controllers/follow_relations_controller.rb:11:in `destroy'
Redirected to http://localhost:3000/users/17
Completed 302 Found in 7ms (ActiveRecord: 0.2ms | Allocations: 1967)

Started GET "/users/17" for ::1 at 2022-04-26 08:40:16 +0900
Processing by UsersController#show as HTML
  Parameters: {"id"=>"17"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 51], ["LIMIT", 1]]
  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 17], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:29:in `set_user'
  Rendering layout layouts/application.html.erb
  Rendering users/show.html.erb within layouts/application
   (0.5ms)  SELECT COUNT(*) FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ?  [["follower_id", 17]]
  ↳ app/views/users/show.html.erb:9
   (0.2ms)  SELECT COUNT(*) FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."follower_id" WHERE "follow_relations"."followed_id" = ?  [["followed_id", 17]]
  ↳ app/views/users/show.html.erb:10
  ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 17], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/show.html.erb:35
  User Exists? (2.3ms)  SELECT 1 AS one FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ? AND "users"."id" = ? LIMIT ?  [["follower_id", 51], ["id", 17], ["LIMIT", 1]]
  ↳ app/models/user.rb:28:in `following?'
  Rendered users/show.html.erb within layouts/application (Duration: 32.8ms | Allocations: 6234)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered layout layouts/application.html.erb (Duration: 49.5ms | Allocations: 10597)
Completed 200 OK in 70ms (Views: 55.5ms | ActiveRecord: 3.9ms | Allocations: 13964)
neutral2010 commented 2 years ago

ペアプロで聞きたいこと

実際に手を動かして確認したり考えておきたいこと

neutral2010 commented 2 years ago

インデックスについて、コンソールで確認

WHERE follower_id = ? も followed_id = ? もどちらも発行されていそうでしょうか?もしそうであれば、どちらのインデックスも使われているのでよいと思います。

?となっているのが、インデックスが使われていることになるの?(user.idのところにもあるから違いそう。) インデックスを貼っていない場合に、SQL文の表示は変わるの?だろうか?

Started GET "/users/51/followers" for 127.0.0.1 at 2022-05-08 18:02:05 +0900
Processing by UsersController#followers as HTML
  Parameters: {"id"=>"51"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 51], ["LIMIT", 1]]
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 51], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:23:in `set_user'
  Rendering layout layouts/application.html.erb
  Rendering users/followers.html.erb within layouts/application
  User Load (0.4ms)  SELECT "users".* FROM "users" INNER JOIN "follow_relations" ON "users"."id" = "follow_relations"."followed_id" WHERE "follow_relations"."follower_id" = ?  [["follower_id", 51]]
  ↳ app/views/users/_follow_relations_index.erb:11
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 3], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/_follow_relations_index.erb:16
  ActiveStorage::Attachment Load (0.6ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 6], ["record_type", "User"], ["name", "avatar"], ["LIMIT", 1]]
  ↳ app/views/users/_follow_relations_index.erb:16
  Rendered users/_follow_relations_index.erb (Duration: 22.2ms | Allocations: 3403)
  Rendered users/followers.html.erb within layouts/application (Duration: 24.5ms | Allocations: 3549)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered layout layouts/application.html.erb (Duration: 40.9ms | Allocations: 7302)
Completed 200 OK in 53ms (Views: 41.1ms | ActiveRecord: 1.6ms | Allocations: 9481)
neutral2010 commented 2 years ago

データベースのユニーク制約について、viewでのチェックの実装を考えてみる

今付けているユニーク制約はデータベースで設定されている。 t.index ["follower_id", "followed_id"], name: "index_follow_relations_on_follower_id_and_followed_id", unique: true

何回もフォローできるようにしてみるとどんなエラーが出るか?

image

これをアプリケーション側で設定するには? 「Active Record バリデーション」のことだった。

# app/models/follow_relation.rb
validates :follower_id, uniqueness: { scope: :followed_id,
                                        message: 'フォローフォロワー関係があります' }

とすると、エラーが変わった。(多分、起こしたいエラーが発生できている。)

image