【问题标题】:Observers vs. Callbacks观察者与回调
【发布时间】:2010-12-04 15:05:29
【问题描述】:

我考虑过使用观察者或回调。 什么时候应该使用观察者?

F.e.您可以执行以下操作:

# User-model
class User << AR
  after_create :send_greeting!

  def send_greeting!
    UserNotifier.deliver_greeting_message(self)
  end

end

#observer
class UserNotifier << AR
  def greeting_message(user)
  ...
  end
end

或者你可以创建一个观察者并让它观察用户何时被创建......

你有什么推荐的?

【问题讨论】:

    标签: ruby-on-rails callback observer-pattern


    【解决方案1】:

    要记住的一个非常重要的区别与 Milan Novota 的回答有关,即 ActiveRecord 上的回调能够取消被调用的操作和所有后​​续回调,而观察者则不能。

    class Model < ActiveRecord::Base
      before_update :disallow_bob
    
      def disallow_bob
      return false if model.name == "bob"
      end
    end
    
    class ModelObserver < ActiveRecord::Observer
      def before_update(model)
        return false if model.name == "mary"
      end
    end
    
    m = Model.create(:name => "whatever")
    
    m.update_attributes(:name => "bob")
    => false -- name will still be "whatever" in database
    
    m.update_attributes(:name => "mary")
    => true -- name will be "mary" in database
    

    观察者只能观察,不能干预。

    【讨论】:

    • 在 rails 3.1 中不再是这种情况,观察者可以通过从 before_* 返回 false 来取消保存操作,这将取消操作,也可能在 after_* 中引发异常以取消操作异常。
    • 谢谢 jrizza,我也遇到过类似的情况,其中一位观察员的失误导致记录无法保存,我认为这是一个不受欢迎的结果。
    • 是的,这很奇怪,他们不再是观察者,观察者中的异常将导致提交失败并且用户会看到异常屏幕。对我来说没有意义。
    【解决方案2】:

    您可以将观察者用作分离或分配责任的一种手段。从基本意义上说 - 如果您的模型代码变得太混乱,开始考虑使用观察者进行一些不必要的行为。观察者的真正力量(至少在我看来)在于它们能够充当模型和其他子系统之间的连接点,这些子系统的功能被所有(或部分)其他类使用。假设您决定向您的应用程序添加 IM 通知 - 假设您希望收到有关系统中某些(或全部)模型的部分(或全部)CRUD 操作的通知。在这种情况下,使用观察者将是理想的——您的通知子系统将与您的业务逻辑完全分离,并且您的模型不会被与其业务无关的行为弄得一团糟。另一个很好的观察者用例是审计子系统。

    【讨论】:

      【解决方案3】:

      回调更短暂:你将它传递给一个函数以调用一次。它是 API 的一部分,因为您通常不能在不传递回调的情况下调用该函数。这个概念与函数的作用紧密结合。通常,您只能传递一个回调..

      示例:运行一个线程并给出一个在线程终止时调用的回调。

      观察者的寿命更长,并且可以随时连接/分离。同一件事可以有多个观察者,他们可以有不同的生命周期。

      示例:在 UI 中显示模型的值并根据用户输入更新模型。

      【讨论】:

        猜你喜欢
        • 2012-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多