web-dev-qa-db-ja.com

オブザーバーとコールバック

オブザーバーやコールバックの使用を考えました。オブザーバーをいつ、何を使用する必要がありますか?

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

または、オブザーバーを作成して、ユーザーが作成されたときにそれを監視させることもできます...

何をお勧めしますか?

34

コールバックはより短命です。一度呼び出される関数にコールバックを渡します。これはAPIの一部であり、通常、コールバックも渡さずに関数を呼び出すことはできません。この概念は、関数の機能と密接に関連しています。通常、渡すことができるコールバックは1つだけです。

例:スレッドを実行し、スレッドの終了時に呼び出されるコールバックを提供します。

オブザーバーは長寿命で、いつでも取り付け/取り外しができます。同じことに対して多くのオブザーバーが存在する可能性があり、それらは異なるライフタイムを持つ可能性があります。

例:UIにモデルの値を表示し、ユーザー入力からモデルを更新します。

11
Aaron Digulla

Milan Novotaの回答に関連する、覚えておくべき非常に重要な違いの1つは、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

オブザーバーは観察するだけで、介入することはできません。

42

オブザーバーは、責任の分離または分散の手段として使用できます。基本的な意味では、モデルコードが乱雑になりすぎた場合は、本質的でない動作にオブザーバーを使用することを検討し始めます。オブザーバーの真の力(少なくとも私が見ているように)は、モデルと、他のすべてのクラス(または一部)によって機能が使用される他のサブシステムとの間の接続ポイントとして機能する能力にあります。アプリケーションにIM通知を追加することにしたとします。たとえば、システム内の一部(またはすべて)のモデルのCRUDアクションの一部(またはすべて)について通知を受け取りたいとします。この場合、オブザーバーを使用するのが理想的です。通知サブシステムはビジネスロジックから完全に分離されたままであり、モデルがビジネス以外の動作で乱雑になることはありません。オブザーバーのもう1つの良いユースケースは、監査サブシステムです。

27
Milan Novota