创建具有嵌套属性的对象时回滚

Rollback when creating object with nested attributes

我有这些模型,我正在使用 Cocoon 和 nested_attributes:

models/report.rb:

class Report < ApplicationRecord
  has_many :option_students

  accepts_nested_attributes_for :option_students, allow_destroy: true
end

models/option_students.rb:

class OptionStudent < ApplicationRecord
  belongs_to :student
  belongs_to :option
  belongs_to :report
end

我正在尝试使用 rails 控制台创建报告。我已经有一个学生和一个选项保存在数据库中。

如果我写:

Report.create(option_students_attributes: [{student_id: 1, option_id: 1}])

控制台输出回滚:

(0.2ms)  BEGIN
  Student Load (0.2ms)  SELECT  "students".* FROM "students" WHERE "students"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
  Option Load (0.1ms)  SELECT  "options".* FROM "options" WHERE "options"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
   (0.2ms)  ROLLBACK

它既不创建报告也不创建 option_student 对象。

但是如果我只输入 Report.create 然后我写

Report.update(1, option_students_attributes: [{student_id: 1, option_id: 1}])

更新报表时成功创建选项student。我做错了什么?我只是将嵌套属性与其他模型一起使用并且它起作用了。

我假设您使用的是 rails 5,它更改了默认要求的 belongs_to 关系。理论上保存嵌套属性时应该没有问题,但是由于保存时(实际上:验证时)尚未设置report-id,因此保存会失败。这可以简单地通过告诉 rails 关联是如何相关的来解决的:

has_many :option_students, inverse_of: :report

或者您可以在 OptionsStudent class 中添加 optional 选项:

belongs_to :report, optional: true 

这是不正确的,它只会跳过验证,但它可能与其他两个关系相关——如果学生或选项并不总是必需的。