Zer*_*nel 3 callback nested-attributes attr-accessor ruby-on-rails-4
请检查伪代码:
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
Run Code Online (Sandbox Code Playgroud)
现在执行时team.update(users_attributes: [{"0" => { dummy: "changed!" }}])
(其他字段除了dummy属性不会改变),它不会触发#generate_addresses_attributes回调,因为它认为没有任何改变,没有保存,没有回调......
所以我的问题是如何触发虚拟属性的回调,或者强制save为accept_nested_attributes_for.
谢谢!
最后,我找到了两个解决方案:
在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
Run Code Online (Sandbox Code Playgroud)我发现 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
Run Code Online (Sandbox Code Playgroud)