after_createコールバック内の関連テーブル作成処理が2回実行される問題

# 結論

* after_createコールバック内で関連テーブルを作成する場合注意が必要。<br>書き方によっては関連テーブルが2つ作成されてしまう。

# 環境
Ruby 3.0.2p107
Rails 6.1.4.6

# やりたかった事
* 生徒が講義の登録を行う多対多構造の作成<br>
* 生徒の登録と同時に必修科目”math”の登録


model/course.rb

```rb
class Course < ApplicationRecord
  has_many :course_students
  has_many :students ,through: :course_students
end
```
model/student.rb

```rb
class Student < ApplicationRecord
  after_create :regist_essensial_course
  has_many :course_students
  has_many :courses, through: :course_students

  private
  def regist_essensial_course
    courses.create(name:"math")
  end
end
```

model/course_student.rb

```rb
class CourseStudent < ApplicationRecord
  belongs_to :course
  belongs_to :student
end
```

# 問題点

このままstudentを登録すると、必修科目が2回登録されてしまいます。

```rb
irb(main):001:0> s = Student.create(name:"tarou")
   (0.5ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  TRANSACTION (0.1ms)  SAVEPOINT active_record_1
  Student Create (0.8ms)  INSERT INTO "students" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "tarou"], ["created_at", "2022-02-15 10:37:40.116549"], ["updated_at", "2022-02-15 10:37:40.116549"]]
  Course Create (0.1ms)  INSERT INTO "courses" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "math"], ["created_at", "2022-02-15 10:37:40.134345"], ["updated_at", "2022-02-15 10:37:40.134345"]]
  CourseStudent Create (0.5ms)  INSERT INTO "course_students" ("course_id", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["course_id", 2], ["student_id", 2], ["created_at", "2022-02-15 10:37:40.139247"], ["updated_at", "2022-02-15 10:37:40.139247"]]
  CourseStudent Create (0.0ms)  INSERT INTO "course_students" ("course_id", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["course_id", 2], ["student_id", 2], ["created_at", "2022-02-15 10:37:40.141084"], ["updated_at", "2022-02-15 10:37:40.141084"]]
  TRANSACTION (0.0ms)  RELEASE SAVEPOINT active_record_1
=> #<Student:0x0000000115ae65a8 id: 2, name: "tarou", created_at: Tue, 15 Feb 2022 10:37:40.116549000 UTC +00:00, updated_at: Tue, 15 Feb 2022 10:37:40.116549000 UTC +00:00>
irb(main):002:0> s.courses
  Course Load (6.5ms)  SELECT "courses".* FROM "courses" INNER JOIN "course_students" ON "courses"."id" = "course_students"."course_id" WHERE "course_students"."student_id" = ?  [["student_id", 2]]
=> 
[#<Course:0x000000011503ce18 id: 2, name: "math", created_at: Tue, 15 Feb 2022 10:37:40.134345000 UTC +00:00, updated_at: Tue, 15 Feb 2022 10:37:40.134345000 UTC +00:00>,
 #<Course:0x00000001242cb238 id: 2, name: "math", created_at: Tue, 15 Feb 2022 10:37:40.134345000 UTC +00:00, updated_at: Tue, 15 Feb 2022 10:37:40.134345000 UTC +00:00>]
```

# 解決方法

下記のように中間テーブルを明示的に作成すると、中間テーブルは1つしか作成されません。


```rb
class Student < ApplicationRecord
  after_create :regist_essensial_course
  has_many :course_students
  has_many :courses, through: :course_students

  private
  def regist_essensial_course
    # courses.create(name:"math")
    c = Course.create(name:"math")
    CourseStudent.create(course:c, student:self)
  end

end
```


```rb
irb(main):001:0> s = Student.create(name:"tarou")
   (0.8ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  TRANSACTION (0.0ms)  SAVEPOINT active_record_1
  Student Create (0.7ms)  INSERT INTO "students" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "tarou"], ["created_at", "2022-02-15 10:48:24.842740"], ["updated_at", "2022-02-15 10:48:24.842740"]]
  Course Create (0.1ms)  INSERT INTO "courses" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "math"], ["created_at", "2022-02-15 10:48:24.863115"], ["updated_at", "2022-02-15 10:48:24.863115"]]
  CourseStudent Create (0.1ms)  INSERT INTO "course_students" ("course_id", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["course_id", 2], ["student_id", 2], ["created_at", "2022-02-15 10:48:24.869031"], ["updated_at", "2022-02-15 10:48:24.869031"]]
  TRANSACTION (0.0ms)  RELEASE SAVEPOINT active_record_1
=> #<Student:0x000000011510e058 id: 2, name: "tarou", created_at: Tue, 15 Feb 2022 10:48:24.842740000 UTC +00:00, updated_at: Tue, 15 Feb 2022 10:48:24.842740000 UTC +00:00>
irb(main):002:0> s.courses
  Course Load (0.2ms)  SELECT "courses".* FROM "courses" INNER JOIN "course_students" ON "courses"."id" = "course_students"."course_id" WHERE "course_students"."student_id" = ?  [["student_id", 2]]
=> [#<Course:0x0000000115cc63f0 id: 2, name: "math", created_at: Tue, 15 Feb 2022 10:48:24.863115000 UTC +00:00, updated_at: Tue, 15 Feb 2022 10:48:24.863115000 UTC +00:00>]

```

# 結論（再掲）

* after_createコールバック内で関連テーブルを作成する場合注意が必要。<br>書き方によっては関連テーブルが2つ作成されてしまう。

# ps

下記のように登録処理をafter_saveコールバックで行えば、明示的に中間テーブルを指定しなくても
必修科目は1つしか登録されません。

model/student.rb

```rb
class Student < ApplicationRecord
  # after_create :regist_essensial_course
  after_save :regist_essensial_course
  has_many :course_students
  has_many :courses, through: :course_students

  private
  def regist_essensial_course
    courses.create(name:"math")
  end
end
```

```rb
irb(main):001:0> s = Student.create(name:"tarou")
   (0.4ms)  SELECT sqlite_version(*)
  TRANSACTION (0.0ms)  begin transaction
  TRANSACTION (0.1ms)  SAVEPOINT active_record_1
  Student Create (0.5ms)  INSERT INTO "students" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "tarou"], ["created_at", "2022-02-15 11:03:57.812200"], ["updated_at", "2022-02-15 11:03:57.812200"]]
  Course Create (0.1ms)  INSERT INTO "courses" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "math"], ["created_at", "2022-02-15 11:03:57.819082"], ["updated_at", "2022-02-15 11:03:57.819082"]]
  CourseStudent Create (0.2ms)  INSERT INTO "course_students" ("course_id", "student_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["course_id", 2], ["student_id", 2], ["created_at", "2022-02-15 11:03:57.825033"], ["updated_at", "2022-02-15 11:03:57.825033"]]
  TRANSACTION (0.0ms)  RELEASE SAVEPOINT active_record_1
=> #<Student:0x000000012447b5b0 id: 2, name: "tarou", created_at: Tue, 15 Feb 2022 11:03:57.812200000 UTC +00:00, updated_at: Tue, 15 Feb 2022 11:03:57.812200000 UTC +00:00>
irb(main):002:0> s.courses
  Course Load (0.2ms)  SELECT "courses".* FROM "courses" INNER JOIN "course_students" ON "courses"."id" = "course_students"."course_id" WHERE "course_students"."student_id" = ?  [["student_id", 2]]
=> [#<Course:0x0000000126d0bfc0 id: 2, name: "math", created_at: Tue, 15 Feb 2022 11:03:57.819082000 UTC +00:00, updated_at: Tue, 15 Feb 2022 11:03:57.819082000 UTC +00:00>]

```

しかし、今回はStudentのcreateの時のみ中間テーブルを作成したかったので、updateの時も走ってしまうafter_saveは使えませんでした。
いろいろなパターンで検証してみましたが、結局after_saveとafter_createで動作が違う理由は分かりませんでした。
どなたか理由がわかる方ご指摘お願いします。