【发布时间】:2011-07-24 20:02:24
【问题描述】:
around_create回调代码什么时候执行,在什么情况下我们应该使用它?
【问题讨论】:
标签: ruby ruby-on-rails-3 model callback
around_create回调代码什么时候执行,在什么情况下我们应该使用它?
【问题讨论】:
标签: ruby ruby-on-rails-3 model callback
我找到的关于回调的更简单明了的解释,如下所示
around_* 回调在动作周围以及 before_* 和 after_* 动作内部被调用。例如:
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
【讨论】:
除了Tom Harrison Jr's answer 关于日志记录和监控之外,我发现关键区别在于获得对操作是否运行的控制。否则,您可以实现自己的 before_* 和 after_* 回调来做同样的事情。
以around_update 为例。假设您有一个不希望更新运行的情况。例如,我正在构建一个 gem,它将草稿保存在另一个 drafts 表中,但不将某些更新保存到“主”表中。
around_update :save_update_for_draft
private
def save_update_for_draft
yield if update_base_record?
end
这里引用的update_base_record? 方法的细节并不重要。您可以看到,如果该方法的计算结果不是 true,则更新操作根本不会运行。
【讨论】:
刚刚为我找到了一个用例:
想象一下多态观察者的情况,观察者在某些情况下需要在保存之前执行操作,而在其他情况下需要在保存之后执行操作。
使用环绕过滤器,您可以在一个块中捕获保存操作并在需要时运行它。
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
【讨论】:
“环绕”过滤器的一个经典用例是衡量性能、记录或进行其他状态监控或修改。
【讨论】:
也有这个问题,现在找到了答案:around_create 基本上允许您在一种方法中同时执行before_create 和after_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
【讨论】:
around_create 在保存带有new? 标志的模型时调用。它可用于添加数据以添加/更改模型的值,调用其他方法等......我无法为这个回调提供特定的用例,但它完成了一组“之前,之后,周围”创建操作的回调。为查找、更新、保存和删除事件设置了类似的“之前、之后、周围”回调集。
【讨论】: