如何挂钩保存!用 rails before_save!打回来

How to hook into save! with rails before_save! callback

有没有办法通过回调挂接到 save!

我正在寻找类似的东西:

class CompositeService < Service
  attr_accessible :subservices

  before_save :save_subservices
  before_save :save_subservices! if bang_save?

  private

  def save_subservices
    @subservices.each(&:save)
  end

  def save_subservices!
    @subservices.each(&:save!)
  end
end

其中 save! 级联并在(伪)关联 subservices 上调用 save!

从技术上讲你可以这样做,但我建议不要在生产中使用这种方法,因为它可能会在更新的 rails 中发生变化。这是错误的。

你可以查看你之前回调的调用栈,看看有没有save!方法。

class CompositeService < Service
  before_save :some_callback

  def some_callback
    lines = caller.select { |line| line =~ /persistence.rb/ && line =~ /save!/ }

    if lines.any?
      @subservices.each(&:save!)
    else
      @subservices.each(&:save)
    end
  end
end

查看 ActiveRecord 自动保存属性:

http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html

我想知道:这个额外的逻辑是否必要?

如果每个 @subservices 上的 save 方法都遵循 ActiveRecord save 语义,那么您可能会免费获得正确的行为。

换句话说,确保您的 save 方法 return truefalse 成功或失败。那么,复合代码就变得这么简单:

class CompositeService < Service
  attr_accessible :subservices

  before_save :save_subservices

  private

  def save_subservices
    @subservices.all?(&:save)
  end
end

如果您的任何子服务未能保存,则 save_subservices 回调将 return false,这将中止回调链。这将导致 save 到 return false 的换行。在 save! 的情况下,它会引发异常。

composite.save
# => false

composite.save!
# => ActiveRecord::RecordNotSaved