LoginSignup
3
1

More than 5 years have passed since last update.

scope を指定したアソシエーションを nested_attributes_for に渡すとアソシエーションを save できない

Posted at

問題

以下の 2 つのモデルが存在するとします。

app/models/lesson.rb
class Lesson < ApplicationRecord
  has_many :lesson_schedules, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
app/models/lesson_schedule.rb
class LessonSchedule < ApplicationRecord
  belongs_to :lesson
end

accepts_nested_attributes_for :lesson_schedules の宣言により、Lesson とそれに紐づく LessonSchedule を次のコードで同時に作成することができます。

lesson =
  Lesson.create(
    title: '仏像彫刻',
    lesson_schedules_attributes: [
      { wday: 0, start_time: '13:00', end_time: '17:30' },
      { wday: 3, start_time: '19:00', end_time: '21:00' }
    ]
  )

lesson.persisted? #=> true
lesson.lesson_schedules.count #=> 2

だがしかし、Lesson モデルで has_many :lesson_schedules に scope を指定すると…

class Lesson < ApplicationRecord
  # has_many の第 2 引数に scope を渡すようにした。
  has_many :lesson_schedules, -> { order(:wday, :start_time, :end_time) }, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
lesson =
  Lesson.create(
    title: '仏像彫刻',
    lesson_schedules_attributes: [
      { wday: 0, start_time: '13:00', end_time: '17:30' },
      { wday: 3, start_time: '19:00', end_time: '21:00' }
    ]
  )
lesson.persisted? #=> false
lesson.errors.full_messages #=> ["Lesson schedules lesson must exist"]

作成できなくなりました。エラーメッセージを確認すると、どうやら LessonSchedule の外部キーが設定できていないようです :sob:

解決策

has_manybelongs_toinverse_of オプションを使います。

app/models/lesson.rb
class Lesson < ApplicationRecord
  has_many :lesson_schedules, -> { order(:wday, :start_time, :end_time) },
           inverse_of: :lesson, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
app/models/lesson_schedule.rb
class LessonSchedule < ApplicationRecord
  belongs_to :lesson, inverse_of: :lesson_schedules
end

こうすると Lesson.create が再び成功するようになりました :smile:

参考

3
1
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
3
1