2009-09-08 11:10:14 -04:00
require 'cases/helper'
2008-01-18 02:31:37 -05:00
require 'models/topic'
require 'models/developer'
require 'models/reply'
2008-06-08 23:45:57 -04:00
require 'models/minimalistic'
2010-04-16 10:20:31 -04:00
require 'models/comment'
2004-11-23 20:04:44 -05:00
2005-09-19 12:34:34 -04:00
class SpecialDeveloper < Developer ; end
2004-11-23 20:04:44 -05:00
2011-02-09 10:37:30 -05:00
class DeveloperObserver < ActiveRecord :: Observer
2011-02-23 19:04:01 -05:00
def calls
@calls || = [ ]
end
2011-02-09 10:37:30 -05:00
def before_save ( developer )
2011-02-23 19:04:01 -05:00
calls << developer
2011-02-09 10:37:30 -05:00
end
end
2010-04-16 13:30:40 -04:00
class SalaryChecker < ActiveRecord :: Observer
observe :special_developer
2010-11-26 13:16:13 -05:00
attr_accessor :last_saved
2010-04-16 13:30:40 -04:00
def before_save ( developer )
return developer . salary > 80000
end
2010-11-26 13:16:13 -05:00
module Implementation
def after_save ( developer )
self . last_saved = developer
end
end
include Implementation
2010-04-16 13:30:40 -04:00
end
2008-02-17 17:52:55 -05:00
class TopicaAuditor < ActiveRecord :: Observer
2007-10-14 01:20:24 -04:00
observe :topic
2008-01-18 02:30:42 -05:00
2004-11-23 20:04:44 -05:00
attr_reader :topic
2008-01-18 02:30:42 -05:00
2004-11-23 20:04:44 -05:00
def after_find ( topic )
@topic = topic
end
end
class TopicObserver < ActiveRecord :: Observer
attr_reader :topic
2008-01-18 02:30:42 -05:00
2004-11-23 20:04:44 -05:00
def after_find ( topic )
@topic = topic
end
2009-09-08 11:10:14 -04:00
# Create an after_save callback, so a notify_observer hook is created
# on :topic.
def after_save ( nothing )
end
2004-11-23 20:04:44 -05:00
end
2008-06-08 23:45:57 -04:00
class MinimalisticObserver < ActiveRecord :: Observer
attr_reader :minimalistic
def after_find ( minimalistic )
@minimalistic = minimalistic
end
end
2004-11-23 20:04:44 -05:00
class MultiObserver < ActiveRecord :: Observer
attr_reader :record
2006-06-30 00:38:24 -04:00
2004-11-23 20:04:44 -05:00
def self . observed_class ( ) [ Topic , Developer ] end
2006-06-30 00:38:24 -04:00
cattr_reader :last_inherited
@@last_inherited = nil
def observed_class_inherited_with_testing ( subclass )
observed_class_inherited_without_testing ( subclass )
@@last_inherited = subclass
end
alias_method_chain :observed_class_inherited , :testing
2004-11-23 20:04:44 -05:00
def after_find ( record )
@record = record
end
end
2010-04-16 10:20:31 -04:00
class ValidatedComment < Comment
attr_accessor :callers
before_validation :record_callers
after_validation do
record_callers
end
def record_callers
callers << self . class if callers
end
end
class ValidatedCommentObserver < ActiveRecord :: Observer
attr_accessor :callers
def after_validation ( model )
callers << self . class if callers
end
end
2008-01-21 12:20:51 -05:00
class LifecycleTest < ActiveRecord :: TestCase
2008-07-31 16:59:53 -04:00
fixtures :topics , :developers , :minimalistics
2004-11-23 20:04:44 -05:00
def test_before_destroy
2010-12-30 15:41:02 -05:00
topic = Topic . find ( 1 )
assert_difference 'Topic.count' , - ( 1 + topic . replies . size ) do
topic . destroy
end
2004-11-23 20:04:44 -05:00
end
2006-06-30 00:38:24 -04:00
2004-11-23 20:04:44 -05:00
def test_auto_observer
2008-02-17 17:52:55 -05:00
topic_observer = TopicaAuditor . instance
assert_nil TopicaAuditor . observed_class
assert_equal [ Topic ] , TopicaAuditor . instance . observed_classes . to_a
2004-11-23 20:04:44 -05:00
2006-06-30 00:38:24 -04:00
topic = Topic . find ( 1 )
assert_equal topic . title , topic_observer . topic . title
2004-11-23 20:04:44 -05:00
end
2006-06-30 00:38:24 -04:00
def test_inferred_auto_observer
2004-11-23 20:04:44 -05:00
topic_observer = TopicObserver . instance
2008-02-17 17:52:55 -05:00
assert_equal Topic , TopicObserver . observed_class
2004-11-23 20:04:44 -05:00
2006-06-30 00:38:24 -04:00
topic = Topic . find ( 1 )
assert_equal topic . title , topic_observer . topic . title
2004-11-23 20:04:44 -05:00
end
2006-06-30 00:38:24 -04:00
2004-11-23 20:04:44 -05:00
def test_observing_two_classes
multi_observer = MultiObserver . instance
topic = Topic . find ( 1 )
2006-06-30 00:38:24 -04:00
assert_equal topic . title , multi_observer . record . title
2004-11-23 20:04:44 -05:00
2006-06-30 00:38:24 -04:00
developer = Developer . find ( 1 )
assert_equal developer . name , multi_observer . record . name
2004-11-23 20:04:44 -05:00
end
2006-06-30 00:38:24 -04:00
2005-09-19 12:34:34 -04:00
def test_observing_subclasses
multi_observer = MultiObserver . instance
developer = SpecialDeveloper . find ( 1 )
2006-06-30 00:38:24 -04:00
assert_equal developer . name , multi_observer . record . name
klass = Class . new ( Developer )
assert_equal klass , multi_observer . last_inherited
developer = klass . find ( 1 )
assert_equal developer . name , multi_observer . record . name
end
2008-07-22 16:38:26 -04:00
def test_after_find_can_be_observed_when_its_not_defined_on_the_model
2008-06-08 23:45:57 -04:00
observer = MinimalisticObserver . instance
assert_equal Minimalistic , MinimalisticObserver . observed_class
minimalistic = Minimalistic . find ( 1 )
2008-07-22 16:38:26 -04:00
assert_equal minimalistic , observer . minimalistic
2008-07-15 14:55:14 -04:00
end
def test_after_find_can_be_observed_when_its_defined_on_the_model
observer = TopicObserver . instance
assert_equal Topic , TopicObserver . observed_class
topic = Topic . find ( 1 )
assert_equal topic , observer . topic
2008-06-08 23:45:57 -04:00
end
2006-06-30 00:38:24 -04:00
def test_invalid_observer
2006-08-05 22:40:24 -04:00
assert_raise ( ArgumentError ) { Topic . observers = Object . new ; Topic . instantiate_observers }
2005-09-19 12:34:34 -04:00
end
2010-04-16 10:20:31 -04:00
test " model callbacks fire before observers are notified " do
callers = [ ]
comment = ValidatedComment . new
comment . callers = ValidatedCommentObserver . instance . callers = callers
comment . valid?
assert_equal [ ValidatedComment , ValidatedComment , ValidatedCommentObserver ] , callers ,
" model callbacks did not fire before observers were notified "
end
2010-04-16 13:30:40 -04:00
test " able to save developer " do
SalaryChecker . instance # activate
developer = SpecialDeveloper . new :name = > 'Roger' , :salary = > 100000
assert developer . save , " developer with normal salary failed to save "
end
test " unable to save developer with low salary " do
SalaryChecker . instance # activate
developer = SpecialDeveloper . new :name = > 'Rookie' , :salary = > 50000
assert ! developer . save , " allowed to save a developer with too low salary "
end
2010-11-26 13:16:13 -05:00
test " able to call methods defined with included module " do # https://rails.lighthouseapp.com/projects/8994/tickets/6065-activerecordobserver-is-not-aware-of-method-added-by-including-modules
SalaryChecker . instance # activate
developer = SpecialDeveloper . create! :name = > 'Roger' , :salary = > 100000
assert_equal developer , SalaryChecker . instance . last_saved
end
2011-02-23 19:04:01 -05:00
def test_observer_is_called_once
observer = DeveloperObserver . instance # activate
observer . calls . clear
2011-02-09 10:37:30 -05:00
developer = Developer . create! :name = > 'Ancestor' , :salary = > 100000
2011-02-23 19:04:01 -05:00
special_developer = SpecialDeveloper . create! :name = > 'Descendent' , :salary = > 100000
assert_equal [ developer , special_developer ] , observer . calls
2011-02-09 10:37:30 -05:00
end
2005-06-10 10:58:02 -04:00
end