aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/lifecycle_test.rb
blob: 5f9e12a7e23352dd09d74d1e043d03149e554249 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
require 'abstract_unit'
require 'fixtures/topic'
require 'fixtures/developer'
require 'fixtures/reply'

class Topic; def after_find() end end
class Developer; def after_find() end end
class SpecialDeveloper < Developer; end

class TopicManualObserver
  include Singleton

  attr_reader :action, :object, :callbacks

  def initialize
    Topic.add_observer(self)
    @callbacks = []
  end

  def update(callback_method, object)
    @callbacks << { "callback_method" => callback_method, "object" => object }
  end

  def has_been_notified?
    !@callbacks.empty?
  end
end

class TopicaObserver < ActiveRecord::Observer
  observe :topic
  
  attr_reader :topic
  
  def after_find(topic)
    @topic = topic
  end
end

class TopicObserver < ActiveRecord::Observer
  attr_reader :topic
  
  def after_find(topic)
    @topic = topic
  end
end

class MultiObserver < ActiveRecord::Observer
  attr_reader :record

  def self.observed_class() [ Topic, Developer ] end

  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

  def after_find(record)
    @record = record
  end
end

class LifecycleTest < Test::Unit::TestCase
  fixtures :topics, :developers

  def test_before_destroy
    assert_equal 2, Topic.count
    Topic.find(1).destroy
    assert_equal 0, Topic.count
  end

  def test_after_save
    ActiveRecord::Base.observers = :topic_manual_observer
    ActiveRecord::Base.instantiate_observers

    topic = Topic.find(1)
    topic.title = "hello"
    topic.save

    assert TopicManualObserver.instance.has_been_notified?
    assert_equal :after_save, TopicManualObserver.instance.callbacks.last["callback_method"]
  end

  def test_observer_update_on_save
    ActiveRecord::Base.observers = TopicManualObserver
    ActiveRecord::Base.instantiate_observers

    topic = Topic.find(1)
    assert TopicManualObserver.instance.has_been_notified?
    assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"]
  end

  def test_auto_observer
    topic_observer = TopicaObserver.instance

    topic = Topic.find(1)
    assert_equal topic.title, topic_observer.topic.title
  end

  def test_inferred_auto_observer
    topic_observer = TopicObserver.instance

    topic = Topic.find(1)
    assert_equal topic.title, topic_observer.topic.title
  end

  def test_observing_two_classes
    multi_observer = MultiObserver.instance

    topic = Topic.find(1)
    assert_equal topic.title, multi_observer.record.title

    developer = Developer.find(1)
    assert_equal developer.name, multi_observer.record.name
  end

  def test_observing_subclasses
    multi_observer = MultiObserver.instance

    developer = SpecialDeveloper.find(1)
    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

  def test_invalid_observer
    assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers }
  end
end