请检查伪代码:
class Team
has_many :users
accepts_nested_attributes_for :users, allow_destroy: true
end
class User
belongs_to :team
has_many :addresses
accepts_nested_attributes_for :addresses
attr_accessor :dummy
before_validation :generate_addresses_attributes
def generate_addresses_attributes
# Use the dummy value to set the addresses_attributes
end
end
现在当执行team.update(users_attributes: [{"0" => { dummy: "changed!" }}])
(其他字段除了伪属性之外不会改变)时,它不会触发#generate_addresses_attributes回调,因为它认为没有任何改变,没有保存,没有回调......
所以我的问题是如何触发虚拟属性的回调,或者强制保存accept_nested_attributes_for。
谢谢!
答案 0 :(得分:6)
最后,我找到了两个解决方案:
在Team模型中添加回调以手动触发回调功能
使用attribute_will_change!
覆盖setter方法:
class User
belongs_to :team
has_many :addresses
accepts_nested_attributes_for :addresses
attr_accessor :dummy
def dummy=(value)
attribute_will_change!("dummy") if @dummy != value
@dummy = value
end
...
end
答案 1 :(得分:2)
我发现在此用例中,对于Rails 5.1 +,attribute
比attr_accessor
更好。
attribute
弄脏了对象,从而在保存对象时触发了回调。
class User
belongs_to :team
has_many :addresses
accepts_nested_attributes_for :addresses
attribute :dummy, :string
before_validation :generate_addresses_attributes
def generate_addresses_attributes
# Use the dummy value to set the addresses_attributes
end
end
答案 2 :(得分:1)
我必须做一些更改才能使用Rails 5.1.3。如果attr_accessor(attr_accessor :dummy
)和setter方法(def dummy=(value)
)的名称相同,则会出现弃用警告,建议使用attribute :dummy
而代码不能按预期工作。如下更改代码有效:
class User
belongs_to :team
has_many :addresses
accepts_nested_attributes_for :addresses
attr_accessor :dummy
def dummy_attr=(value)
attribute_will_change!(:dummy)
self.dummy = value
end
...
end
:dummy_attr
应在强参数中使用,而不是:dummy