require"cases/helper"require'models/topic'require'models/developer'require'models/reply'require'models/minimalistic'classTopic;defafter_find()endendclassDeveloper;defafter_find()endendclassSpecialDeveloper<Developer;endclassTopicManualObserverincludeSingletonattr_reader:action,:object,:callbacksdefinitializeTopic.add_observer(self)@callbacks=[]enddefupdate(callback_method,object)@callbacks<<{"callback_method"=>callback_method,"object"=>object}enddefhas_been_notified?!@callbacks.empty?endendclassTopicaAuditor<ActiveRecord::Observerobserve:topicattr_reader:topicdefafter_find(topic)@topic=topicendendclassTopicObserver<ActiveRecord::Observerattr_reader:topicdefafter_find(topic)@topic=topicendendclassMinimalisticObserver<ActiveRecord::Observerattr_reader:minimalisticdefafter_find(minimalistic)@minimalistic=minimalisticendendclassMultiObserver<ActiveRecord::Observerattr_reader:recorddefself.observed_class()[Topic,Developer]endcattr_reader:last_inherited@@last_inherited=nildefobserved_class_inherited_with_testing(subclass)observed_class_inherited_without_testing(subclass)@@last_inherited=subclassendalias_method_chain:observed_class_inherited,:testingdefafter_find(record)@record=recordendendclassLifecycleTest<ActiveRecord::TestCasefixtures:topics,:developers,:minimalisticsdeftest_before_destroyoriginal_count=Topic.count(topic_to_be_destroyed=Topic.find(1)).destroyassert_equaloriginal_count-(1+topic_to_be_destroyed.replies.size),Topic.countenddeftest_after_saveActiveRecord::Base.observers=:topic_manual_observerActiveRecord::Base.instantiate_observerstopic=Topic.find(1)topic.title="hello"topic.saveassertTopicManualObserver.instance.has_been_notified?assert_equal:after_save,TopicManualObserver.instance.callbacks.last["callback_method"]enddeftest_observer_update_on_saveActiveRecord::Base.observers=TopicManualObserverActiveRecord::Base.instantiate_observerstopic=Topic.find(1)assertTopicManualObserver.instance.has_been_notified?assert_equal:after_find,TopicManualObserver.instance.callbacks.first["callback_method"]enddeftest_auto_observertopic_observer=TopicaAuditor.instanceassert_nilTopicaAuditor.observed_classassert_equal[Topic],TopicaAuditor.instance.observed_classes.to_atopic=Topic.find(1)assert_equaltopic.title,topic_observer.topic.titleenddeftest_inferred_auto_observertopic_observer=TopicObserver.instanceassert_equalTopic,TopicObserver.observed_classtopic=Topic.find(1)assert_equaltopic.title,topic_observer.topic.titleenddeftest_observing_two_classesmulti_observer=MultiObserver.instancetopic=Topic.find(1)assert_equaltopic.title,multi_observer.record.titledeveloper=Developer.find(1)assert_equaldeveloper.name,multi_observer.record.nameenddeftest_observing_subclassesmulti_observer=MultiObserver.instancedeveloper=SpecialDeveloper.find(1)assert_equaldeveloper.name,multi_observer.record.nameklass=Class.new(Developer)assert_equalklass,multi_observer.last_inheriteddeveloper=klass.find(1)assert_equaldeveloper.name,multi_observer.record.nameenddeftest_after_find_can_be_observed_when_its_not_defined_on_the_modelobserver=MinimalisticObserver.instanceassert_equalMinimalistic,MinimalisticObserver.observed_classminimalistic=Minimalistic.find(1)assert_equalminimalistic,observer.minimalisticenddeftest_after_find_can_be_observed_when_its_defined_on_the_modelobserver=TopicObserver.instanceassert_equalTopic,TopicObserver.observed_classtopic=Topic.find(1)assert_equaltopic,observer.topicenddeftest_after_find_is_not_created_if_its_not_used# use a fresh class so an observer can't have defined an# after_find on itmodel_class=Class.new(ActiveRecord::Base)observer_class=Class.new(ActiveRecord::Observer)observer_class.observe(model_class)observer=observer_class.instanceassert!model_class.method_defined?(:after_find)enddeftest_after_find_is_not_clobbered_if_it_already_exists# use a fresh observer class so we can instantiate it (Observer is# a Singleton)model_class=Class.new(ActiveRecord::Base)dodefafter_find;endendoriginal_method=model_class.instance_method(:after_find)observer_class=Class.new(ActiveRecord::Observer)dodefafter_find;endendobserver_class.observe(model_class)observer=observer_class.instanceassert_equaloriginal_method,model_class.instance_method(:after_find)enddeftest_invalid_observerassert_raise(ArgumentError){Topic.observers=Object.new;Topic.instantiate_observers}endend