Вложенные атрибуты Rails дочерние колбэки не запускаются - PullRequest
21 голосов
/ 20 февраля 2012

У меня странная проблема, когда дочерние обратные вызовы не запускаются при обновлении родителя ...

У меня есть следующие настройки модели:

class Budget < ActiveRecord::Base
  has_many :line_items
  accepts_nested_attributes_for :line_items
end

class LineItem < ActiveRecord::Base
  belongs_to :budget

  before_save :update_totals

  private
  def update_totals
    self.some_field = value
  end
end

В моей форме у меня есть вложенные поля (построенные с использованием fields_for):

= form_for @budget do |f|
  = f.text_field :name
  = f.fields_for :line_items do |ff|
    = ff.text_field :amount

Почему обратный вызов update_totals для ребенка никогда не запускается / что я могу сделатьразжечь огонь?

Ответы [ 2 ]

35 голосов
/ 20 июля 2012

У меня была такая же проблема.before_save обратный вызов не вызывается, когда модель не изменяется.

Вы обновляете line_items, а не budget, поэтому rails считает, что оно не обновлено, и не вызывает saveдля него.

Вам нужно изменить before_save на after_validation, чтобы он вызывался, даже если у модели нет измененных атрибутов.И когда в этом обратном вызове вы измените некоторые атрибуты, rails увидит, что ваша модель изменилась, и вызовет save.

9 голосов
/ 05 февраля 2014

Старый вопрос, я знаю, но он все еще появляется первым в поиске.Я думаю, что в этой статье есть решение:

Rails, вложенные атрибуты и обратные вызовы before_save

Если я правильно понимаю эту статью, проблема (как объясняет @AntonDieterle вего ответ) заключается в том, что обратный вызов ребенка не запускается, потому что родитель не "грязный".Решение этой арктики состоит в том, чтобы «заставить» ее запачкать, вызвав attr_name_will_change! для родительского атрибута, который, по сути, не изменяется.См. [Active Model Dirty] в Rails API 2 .

Решение Антона использовать after_validation вместо before_save звучит проще, но я хотел бы предложить альтернативу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...