【问题标题】:Rails4: How to trigger the callback for attr_accessor while using accepts_nested_attributes_forRails4:如何在使用 accept_nested_attributes_for 时触发 attr_accessor 的回调
【发布时间】:2015-03-16 09:46:19
【问题描述】:

请检查伪代码:

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!" }}])时(除了dummy属性其他字段不会改变),它不会触发#generate_addresses_attributes回调,因为它认为没有任何变化,没有保存,没有回调......

所以我的问题是如何触发虚拟属性的回调,或者强制保存 Accept_nested_attributes_for。

谢谢!

【问题讨论】:

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


    【解决方案1】:

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

    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
      

    【讨论】:

    • 你忘记了 if 上的 @,应该是:attribute_will_change!("dummy") if @dummy != value
    【解决方案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
    

    【讨论】:

      【解决方案3】:

      我必须进行一些更改才能使其与 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

      【讨论】:

        猜你喜欢
        • 2012-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-12
        • 2013-01-11
        • 1970-01-01
        • 2015-10-18
        • 1970-01-01
        相关资源
        最近更新 更多