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

时间:2015-04-28 13:43:19

标签: ruby-on-rails 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!级联,并在(虚假)关联save!上调用subservices

3 个答案:

答案 0 :(得分:2)

从技术上讲,你可以做到这一点,但我建议不要在生产中使用这种方法,因为它可以在更新的轨道中改变。这是错的。

您可以检查回调之前的调用堆栈并检查是否有保存!方法

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

答案 1 :(得分:1)

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

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

换句话说,请确保您的save方法返回truefalse表示成功或失败。然后,复合代码变得如此简单:

class CompositeService < Service
  attr_accessible :subservices

  before_save :save_subservices

  private

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

如果您的任何子服务无法保存,则save_subservices回调将返回false,这将中止回调链。这将导致包裹save返回false。在save!的情况下,它会引发异常。

composite.save
# => false

composite.save!
# => ActiveRecord::RecordNotSaved

答案 2 :(得分:0)