Rails模型中around_create回调的目的是什么?

问题描述 投票:14回答:6

什么时候是around_create回调代码执行,在什么情况下我们应该使用它?

ruby ruby-on-rails-3 model callback
6个回答
33
投票

也有这个问题,现在已经找到了答案:around_create允许你在一种方法中基本上同时做before_createafter_create。你必须使用yield来执行之间的保存。

class MyModel < ActiveRecord::Base
  around_create :my_callback_method

  private
    def my_call_back_method
      # do some "before_create" stuff here

      yield  # this makes the save happen

      # do some "after_create" stuff here
    end
end

3
投票

刚刚找到一个用例:

想象一下多态观察者的情况,观察者在某些情况下需要在保存之前执行操作,在其他情况下需要执行操作。

使用around过滤器,您可以捕获块中的保存操作并在需要时运行它。

class SomeClass < ActiveRecord::Base

end

class SomeClassObserver < ActiveRecord::Observer
  def around_create(instance, &block)
    Watcher.perform_action(instance, &block)
  end
end

# polymorphic watcher
class Watcher
  def perform_action(some_class, &block)
    if condition?
      Watcher::First.perform_action(some_class, &block)
    else
      Watcher::Second.perform_action(some_class, &block)
    end
  end
end

class Watcher::First
  def perform_action(some_class, &block)
    # update attributes
    some_class.field = "new value"

    # save
    block.call
  end
end

class Watcher::Second
  def perform_action(some_class, &block)
    # save
    block.call

    # Do some stuff with id
    Mailer.delay.email( some_class.id )
  end
end

1
投票

“around”过滤器的典型用例是测量性能,或记录或执行其他状态监视或修改。


1
投票

除了Tom Harrison Jr's answer关于记录和监控之外,我发现关键的区别在于控制操作是否完全运行。否则,你可以实现自己的before_*after_*回调来做同样的事情。

around_update为例。假设您有一个不希望更新运行的情况。例如,我正在构建一个gem,它将草稿保存在另一个drafts表中,但不保存对“master”表的某些更新。

around_update :save_update_for_draft

private

def save_update_for_draft
  yield if update_base_record?
end

这里引用的update_base_record?方法的细节并不重要。您可以看到,如果该方法未评估为true,则更新操作将无法运行。


0
投票

保存带有around_create标志的模型时调用new?。它可以用来添加数据来添加/更改模型的值,调用其他方法等等...我不能知道这个回调的特定用例,但它完成了一组“之前,之后,周围”创建操作的回调。对于查找,更新,保存和删除事件,存在类似的“之前,之后,周围”回调集。


0
投票

关于我发现的回调的简单而整洁的解释如下

围绕操作以及before_ *和after_ *操作内部调用around_ *回调。例如:

class User
  def before_save
    puts 'before save'
  end

  def after_save
    puts 'after_save'
  end

  def around_save
    puts 'in around save'
    yield # User saved
    puts 'out around save'
  end
end

User.save
  before save
  in around save
  out around save
  after_save
=> true

最初发布here

© www.soinside.com 2019 - 2024. All rights reserved.