我有一个模型Guest
,它采用Numberplate
的嵌套属性。
Guest
采用STI(单表继承)并继承自Person
。为了防止需要额外查询或加入另一个表,我将人员类型保存在person_type
表中名为Numberplate
的字段中。这样,我知道客人拥有哪些Numberplates而无需加入人员表。
由于此设置,我需要在person_type
上手动设置正确的Numberplate
(还有其他人类型)。我在before_validation
模型上将其实现为Numberplate
回调:
before_validation do
self.person_type = self.person.type
end
实际的实现有点通用,但归结为此。
现在我将在控制台的一个调用中创建一个Guest
和Numberplate
,这一切都按预期工作:
Numberplate.new({person: Guest.new({company: Company.first}), plate: 'EFEF98'})
person_type
实例上的Numberplate
已正确设置为"Guest"
。
当我有一个API端点允许嵌套属性在一个请求中创建Guest
和Numberplate
时,会出现问题。奇怪的是,person_type
按预期存储为"Person'
而不是"Guest"
。我进行了一些调试,person_type
在before_validation
回调中设置正确,但在该回调和before_save
回调之间,person_type
突然变为"Person"
。
我试图覆盖person_type
setter并在设置时记录。奇怪的是,在2个ActiveRecord回调之间没有调用setter。
我有点惊讶于这种行为是如何引入的,以及这是否是某个地方的Rails核心中的错误或者我没有考虑到什么。我目前的解决方法是将person_type
设置为额外的before_save
回调,但这不是最佳解决方案。
相关型号:
class Guest < Person
accepts_nested_attributes_for :numberplates
end
class Numberplate < ApplicationRecord
before_validation do
self.person_type = self.person.type
end
after_validation do
# person_type is correctly set to "Guest"
puts self.inspect
end
before_create do
# person_type is now suddenly set to "Person"
puts self.inspect
end
end
答案 0 :(得分:0)
所以我想通了。
在Person
课程中我有这个:
has_many :numberplates, as: :person, inverse_of: :person
as: :person
部分不应该出现并引入此行为。它是由于早期从多态性迁移到STI,因此是一个被遗忘的遗留物。一旦我删除了这一切,一切按预期工作。