Rails4:如何在使用accepts_nested_attributes_for时触发attr_accessor的回调

时间:2015-03-16 09:46:20

标签: ruby-on-rails-4 callback nested-attributes attr-accessor

请检查伪代码:

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。

谢谢!

3 个答案:

答案 0 :(得分:6)

最后,我找到了两个解决方案:

  1. 在Team模型中添加回调以手动触发回调功能

  2. 使用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 +,attributeattr_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