rails-observers 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,249 +0,0 @@
1
- require 'helper'
2
-
3
- class SpecialDeveloper < Developer; end
4
-
5
- class DeveloperObserver < ActiveRecord::Observer
6
- def calls
7
- @calls ||= []
8
- end
9
-
10
- def before_save(developer)
11
- calls << developer
12
- end
13
- end
14
-
15
- class SalaryChecker < ActiveRecord::Observer
16
- observe :special_developer
17
- attr_accessor :last_saved
18
-
19
- def before_save(developer)
20
- return developer.salary > 80000
21
- end
22
-
23
- module Implementation
24
- def after_save(developer)
25
- self.last_saved = developer
26
- end
27
- end
28
- include Implementation
29
- end
30
-
31
- class TopicaAuditor < ActiveRecord::Observer
32
- observe :topic
33
-
34
- attr_reader :topic
35
-
36
- def after_find(topic)
37
- @topic = topic
38
- end
39
- end
40
-
41
- class TopicObserver < ActiveRecord::Observer
42
- attr_reader :topic
43
-
44
- def after_find(topic)
45
- @topic = topic
46
- end
47
-
48
- # Create an after_save callback, so a notify_observer hook is created
49
- # on :topic.
50
- def after_save(nothing)
51
- end
52
- end
53
-
54
- class MinimalisticObserver < ActiveRecord::Observer
55
- attr_reader :minimalistic
56
-
57
- def after_find(minimalistic)
58
- @minimalistic = minimalistic
59
- end
60
- end
61
-
62
- class MultiObserver < ActiveRecord::Observer
63
- attr_reader :record
64
-
65
- def self.observed_class() [ Topic, Developer ] end
66
-
67
- cattr_reader :last_inherited
68
- @@last_inherited = nil
69
-
70
- def observed_class_inherited_with_testing(subclass)
71
- observed_class_inherited_without_testing(subclass)
72
- @@last_inherited = subclass
73
- end
74
-
75
- alias_method_chain :observed_class_inherited, :testing
76
-
77
- def after_find(record)
78
- @record = record
79
- end
80
- end
81
-
82
- class ValidatedComment < Comment
83
- attr_accessor :callers
84
-
85
- before_validation :record_callers
86
-
87
- after_validation do
88
- record_callers
89
- end
90
-
91
- def record_callers
92
- callers << self.class if callers
93
- end
94
- end
95
-
96
- class ValidatedCommentObserver < ActiveRecord::Observer
97
- attr_accessor :callers
98
-
99
- def after_validation(model)
100
- callers << self.class if callers
101
- end
102
- end
103
-
104
-
105
- class AroundTopic < Topic
106
- end
107
-
108
- class AroundTopicObserver < ActiveRecord::Observer
109
- observe :around_topic
110
- def topic_ids
111
- @topic_ids ||= []
112
- end
113
-
114
- def around_save(topic)
115
- topic_ids << topic.id
116
- yield(topic)
117
- topic_ids << topic.id
118
- end
119
- end
120
-
121
- class LifecycleTest < ActiveRecord::TestCase
122
- fixtures :topics, :developers, :minimalistics
123
-
124
- def test_before_destroy
125
- topic = Topic.find(1)
126
- assert_difference 'Topic.count', -(1 + topic.replies.size) do
127
- topic.destroy
128
- end
129
- end
130
-
131
- def test_auto_observer
132
- topic_observer = TopicaAuditor.instance
133
- assert_nil TopicaAuditor.observed_class
134
- assert_equal [Topic], TopicaAuditor.observed_classes.to_a
135
-
136
- topic = Topic.find(1)
137
- assert_equal topic.title, topic_observer.topic.title
138
- end
139
-
140
- def test_inferred_auto_observer
141
- topic_observer = TopicObserver.instance
142
- assert_equal Topic, TopicObserver.observed_class
143
-
144
- topic = Topic.find(1)
145
- assert_equal topic.title, topic_observer.topic.title
146
- end
147
-
148
- def test_observing_two_classes
149
- multi_observer = MultiObserver.instance
150
-
151
- topic = Topic.find(1)
152
- assert_equal topic.title, multi_observer.record.title
153
-
154
- developer = Developer.find(1)
155
- assert_equal developer.name, multi_observer.record.name
156
- end
157
-
158
- def test_observing_subclasses
159
- multi_observer = MultiObserver.instance
160
-
161
- developer = SpecialDeveloper.find(1)
162
- assert_equal developer.name, multi_observer.record.name
163
-
164
- klass = Class.new(Developer)
165
- assert_equal klass, multi_observer.last_inherited
166
-
167
- developer = klass.find(1)
168
- assert_equal developer.name, multi_observer.record.name
169
- end
170
-
171
- def test_after_find_can_be_observed_when_its_not_defined_on_the_model
172
- observer = MinimalisticObserver.instance
173
- assert_equal Minimalistic, MinimalisticObserver.observed_class
174
-
175
- minimalistic = Minimalistic.find(1)
176
- assert_equal minimalistic, observer.minimalistic
177
- end
178
-
179
- def test_after_find_can_be_observed_when_its_defined_on_the_model
180
- observer = TopicObserver.instance
181
- assert_equal Topic, TopicObserver.observed_class
182
-
183
- topic = Topic.find(1)
184
- assert_equal topic, observer.topic
185
- end
186
-
187
- def test_invalid_observer
188
- assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers }
189
- end
190
-
191
- test "model callbacks fire before observers are notified" do
192
- callers = []
193
-
194
- comment = ValidatedComment.new
195
- comment.callers = ValidatedCommentObserver.instance.callers = callers
196
-
197
- comment.valid?
198
- assert_equal [ValidatedComment, ValidatedComment, ValidatedCommentObserver], callers,
199
- "model callbacks did not fire before observers were notified"
200
- end
201
-
202
- test "able to save developer" do
203
- SalaryChecker.instance # activate
204
- developer = SpecialDeveloper.new :name => 'Roger', :salary => 100000
205
- assert developer.save, "developer with normal salary failed to save"
206
- end
207
-
208
- test "unable to save developer with low salary" do
209
- SalaryChecker.instance # activate
210
- developer = SpecialDeveloper.new :name => 'Rookie', :salary => 50000
211
- assert !developer.save, "allowed to save a developer with too low salary"
212
- end
213
-
214
- 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
215
- SalaryChecker.instance # activate
216
- developer = SpecialDeveloper.create! :name => 'Roger', :salary => 100000
217
- assert_equal developer, SalaryChecker.instance.last_saved
218
- end
219
-
220
- test "around filter from observer should accept block" do
221
- observer = AroundTopicObserver.instance
222
- topic = AroundTopic.new
223
- topic.save
224
- assert_nil observer.topic_ids.first
225
- assert_not_nil observer.topic_ids.last
226
- end
227
-
228
- test "able to disable observers" do
229
- observer = DeveloperObserver.instance # activate
230
- observer.calls.clear
231
-
232
- ActiveRecord::Base.observers.disable DeveloperObserver do
233
- Developer.create! :name => 'Ancestor', :salary => 100000
234
- SpecialDeveloper.create! :name => 'Descendent', :salary => 100000
235
- end
236
-
237
- assert_equal [], observer.calls
238
- end
239
-
240
- def test_observer_is_called_once
241
- observer = DeveloperObserver.instance # activate
242
- observer.calls.clear
243
-
244
- developer = Developer.create! :name => 'Ancestor', :salary => 100000
245
- special_developer = SpecialDeveloper.create! :name => 'Descendent', :salary => 100000
246
-
247
- assert_equal [developer, special_developer], observer.calls
248
- end
249
- end
@@ -1,27 +0,0 @@
1
- class ORM
2
- include ActiveModel::Observing
3
-
4
- def save
5
- notify_observers :before_save
6
- end
7
-
8
- class Observer < ActiveModel::Observer
9
- def before_save_invocations
10
- @before_save_invocations ||= []
11
- end
12
-
13
- def before_save(record)
14
- before_save_invocations << record
15
- end
16
- end
17
- end
18
-
19
- class Widget < ORM; end
20
- class Budget < ORM; end
21
- class WidgetObserver < ORM::Observer; end
22
- class BudgetObserver < ORM::Observer; end
23
- class AuditTrail < ORM::Observer
24
- observe :widget, :budget
25
- end
26
-
27
- ORM.instantiate_observers
@@ -1,222 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'active_model'
3
- require 'rails/observers/active_model/active_model'
4
- require 'models/observers'
5
-
6
- class ObserverArrayTest < ActiveModel::TestCase
7
- def teardown
8
- ORM.observers.enable :all
9
- Budget.observers.enable :all
10
- Widget.observers.enable :all
11
- end
12
-
13
- def assert_observer_notified(model_class, observer_class)
14
- observer_class.instance.before_save_invocations.clear
15
- model_instance = model_class.new
16
- model_instance.save
17
- assert_equal [model_instance], observer_class.instance.before_save_invocations
18
- end
19
-
20
- def assert_observer_not_notified(model_class, observer_class)
21
- observer_class.instance.before_save_invocations.clear
22
- model_instance = model_class.new
23
- model_instance.save
24
- assert_equal [], observer_class.instance.before_save_invocations
25
- end
26
-
27
- test "all observers are enabled by default" do
28
- assert_observer_notified Widget, WidgetObserver
29
- assert_observer_notified Budget, BudgetObserver
30
- assert_observer_notified Widget, AuditTrail
31
- assert_observer_notified Budget, AuditTrail
32
- end
33
-
34
- test "can disable individual observers using a class constant" do
35
- ORM.observers.disable WidgetObserver
36
-
37
- assert_observer_not_notified Widget, WidgetObserver
38
- assert_observer_notified Budget, BudgetObserver
39
- assert_observer_notified Widget, AuditTrail
40
- assert_observer_notified Budget, AuditTrail
41
- end
42
-
43
- test "can enable individual observers using a class constant" do
44
- ORM.observers.disable :all
45
- ORM.observers.enable AuditTrail
46
-
47
- assert_observer_not_notified Widget, WidgetObserver
48
- assert_observer_not_notified Budget, BudgetObserver
49
- assert_observer_notified Widget, AuditTrail
50
- assert_observer_notified Budget, AuditTrail
51
- end
52
-
53
- test "can disable individual observers using a symbol" do
54
- ORM.observers.disable :budget_observer
55
-
56
- assert_observer_notified Widget, WidgetObserver
57
- assert_observer_not_notified Budget, BudgetObserver
58
- assert_observer_notified Widget, AuditTrail
59
- assert_observer_notified Budget, AuditTrail
60
- end
61
-
62
- test "can enable individual observers using a symbol" do
63
- ORM.observers.disable :all
64
- ORM.observers.enable :audit_trail
65
-
66
- assert_observer_not_notified Widget, WidgetObserver
67
- assert_observer_not_notified Budget, BudgetObserver
68
- assert_observer_notified Widget, AuditTrail
69
- assert_observer_notified Budget, AuditTrail
70
- end
71
-
72
- test "can disable multiple observers at a time" do
73
- ORM.observers.disable :widget_observer, :budget_observer
74
-
75
- assert_observer_not_notified Widget, WidgetObserver
76
- assert_observer_not_notified Budget, BudgetObserver
77
- assert_observer_notified Widget, AuditTrail
78
- assert_observer_notified Budget, AuditTrail
79
- end
80
-
81
- test "can enable multiple observers at a time" do
82
- ORM.observers.disable :all
83
- ORM.observers.enable :widget_observer, :budget_observer
84
-
85
- assert_observer_notified Widget, WidgetObserver
86
- assert_observer_notified Budget, BudgetObserver
87
- assert_observer_not_notified Widget, AuditTrail
88
- assert_observer_not_notified Budget, AuditTrail
89
- end
90
-
91
- test "can disable all observers using :all" do
92
- ORM.observers.disable :all
93
-
94
- assert_observer_not_notified Widget, WidgetObserver
95
- assert_observer_not_notified Budget, BudgetObserver
96
- assert_observer_not_notified Widget, AuditTrail
97
- assert_observer_not_notified Budget, AuditTrail
98
- end
99
-
100
- test "can enable all observers using :all" do
101
- ORM.observers.disable :all
102
- ORM.observers.enable :all
103
-
104
- assert_observer_notified Widget, WidgetObserver
105
- assert_observer_notified Budget, BudgetObserver
106
- assert_observer_notified Widget, AuditTrail
107
- assert_observer_notified Budget, AuditTrail
108
- end
109
-
110
- test "can disable observers on individual models without affecting those observers on other models" do
111
- Widget.observers.disable :all
112
-
113
- assert_observer_not_notified Widget, WidgetObserver
114
- assert_observer_notified Budget, BudgetObserver
115
- assert_observer_not_notified Widget, AuditTrail
116
- assert_observer_notified Budget, AuditTrail
117
- end
118
-
119
- test "can enable observers on individual models without affecting those observers on other models" do
120
- ORM.observers.disable :all
121
- Budget.observers.enable AuditTrail
122
-
123
- assert_observer_not_notified Widget, WidgetObserver
124
- assert_observer_not_notified Budget, BudgetObserver
125
- assert_observer_not_notified Widget, AuditTrail
126
- assert_observer_notified Budget, AuditTrail
127
- end
128
-
129
- test "can disable observers for the duration of a block" do
130
- yielded = false
131
- ORM.observers.disable :budget_observer do
132
- yielded = true
133
- assert_observer_notified Widget, WidgetObserver
134
- assert_observer_not_notified Budget, BudgetObserver
135
- assert_observer_notified Widget, AuditTrail
136
- assert_observer_notified Budget, AuditTrail
137
- end
138
-
139
- assert yielded
140
- assert_observer_notified Widget, WidgetObserver
141
- assert_observer_notified Budget, BudgetObserver
142
- assert_observer_notified Widget, AuditTrail
143
- assert_observer_notified Budget, AuditTrail
144
- end
145
-
146
- test "can enable observers for the duration of a block" do
147
- yielded = false
148
- Widget.observers.disable :all
149
-
150
- Widget.observers.enable :all do
151
- yielded = true
152
- assert_observer_notified Widget, WidgetObserver
153
- assert_observer_notified Budget, BudgetObserver
154
- assert_observer_notified Widget, AuditTrail
155
- assert_observer_notified Budget, AuditTrail
156
- end
157
-
158
- assert yielded
159
- assert_observer_not_notified Widget, WidgetObserver
160
- assert_observer_notified Budget, BudgetObserver
161
- assert_observer_not_notified Widget, AuditTrail
162
- assert_observer_notified Budget, AuditTrail
163
- end
164
-
165
- test "raises an appropriate error when a developer accidentally enables or disables the wrong class (i.e. Widget instead of WidgetObserver)" do
166
- assert_raise ArgumentError do
167
- ORM.observers.enable :widget
168
- end
169
-
170
- assert_raise ArgumentError do
171
- ORM.observers.enable Widget
172
- end
173
-
174
- assert_raise ArgumentError do
175
- ORM.observers.disable :widget
176
- end
177
-
178
- assert_raise ArgumentError do
179
- ORM.observers.disable Widget
180
- end
181
- end
182
-
183
- test "allows #enable at the superclass level to override #disable at the subclass level when called last" do
184
- Widget.observers.disable :all
185
- ORM.observers.enable :all
186
-
187
- assert_observer_notified Widget, WidgetObserver
188
- assert_observer_notified Budget, BudgetObserver
189
- assert_observer_notified Widget, AuditTrail
190
- assert_observer_notified Budget, AuditTrail
191
- end
192
-
193
- test "allows #disable at the superclass level to override #enable at the subclass level when called last" do
194
- Budget.observers.enable :audit_trail
195
- ORM.observers.disable :audit_trail
196
-
197
- assert_observer_notified Widget, WidgetObserver
198
- assert_observer_notified Budget, BudgetObserver
199
- assert_observer_not_notified Widget, AuditTrail
200
- assert_observer_not_notified Budget, AuditTrail
201
- end
202
-
203
- test "can use the block form at different levels of the hierarchy" do
204
- yielded = false
205
- Widget.observers.disable :all
206
-
207
- ORM.observers.enable :all do
208
- yielded = true
209
- assert_observer_notified Widget, WidgetObserver
210
- assert_observer_notified Budget, BudgetObserver
211
- assert_observer_notified Widget, AuditTrail
212
- assert_observer_notified Budget, AuditTrail
213
- end
214
-
215
- assert yielded
216
- assert_observer_not_notified Widget, WidgetObserver
217
- assert_observer_notified Budget, BudgetObserver
218
- assert_observer_not_notified Widget, AuditTrail
219
- assert_observer_notified Budget, AuditTrail
220
- end
221
- end
222
-
@@ -1,183 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'active_model'
3
- require 'rails/observers/active_model/active_model'
4
-
5
- class ObservedModel
6
- include ActiveModel::Observing
7
-
8
- class Observer
9
- end
10
- end
11
-
12
- class FooObserver < ActiveModel::Observer
13
- class << self
14
- public :new
15
- end
16
-
17
- attr_accessor :stub
18
-
19
- def on_spec(record, *args)
20
- stub.event_with(record, *args) if stub
21
- end
22
-
23
- def around_save(record)
24
- yield :in_around_save
25
- end
26
- end
27
-
28
- class Foo
29
- include ActiveModel::Observing
30
- end
31
-
32
- class ObservingTest < ActiveModel::TestCase
33
- def setup
34
- ObservedModel.observers.clear
35
- end
36
-
37
- test "initializes model with no cached observers" do
38
- assert ObservedModel.observers.empty?, "Not empty: #{ObservedModel.observers.inspect}"
39
- end
40
-
41
- test "stores cached observers in an array" do
42
- ObservedModel.observers << :foo
43
- assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
44
- end
45
-
46
- test "flattens array of assigned cached observers" do
47
- ObservedModel.observers = [[:foo], :bar]
48
- assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
49
- assert ObservedModel.observers.include?(:bar), ":bar not in #{ObservedModel.observers.inspect}"
50
- end
51
-
52
- test "uses an ObserverArray so observers can be disabled" do
53
- ObservedModel.observers = [:foo, :bar]
54
- assert ObservedModel.observers.is_a?(ActiveModel::ObserverArray)
55
- end
56
-
57
- test "instantiates observer names passed as strings" do
58
- ObservedModel.observers << 'foo_observer'
59
- FooObserver.expects(:instance)
60
- ObservedModel.instantiate_observers
61
- end
62
-
63
- test "instantiates observer names passed as symbols" do
64
- ObservedModel.observers << :foo_observer
65
- FooObserver.expects(:instance)
66
- ObservedModel.instantiate_observers
67
- end
68
-
69
- test "instantiates observer classes" do
70
- ObservedModel.observers << ObservedModel::Observer
71
- ObservedModel::Observer.expects(:instance)
72
- ObservedModel.instantiate_observers
73
- end
74
-
75
- test "raises an appropriate error when a developer accidentally adds the wrong class (i.e. Widget instead of WidgetObserver)" do
76
- assert_raise ArgumentError do
77
- ObservedModel.observers = ['string']
78
- ObservedModel.instantiate_observers
79
- end
80
- assert_raise ArgumentError do
81
- ObservedModel.observers = [:string]
82
- ObservedModel.instantiate_observers
83
- end
84
- assert_raise ArgumentError do
85
- ObservedModel.observers = [String]
86
- ObservedModel.instantiate_observers
87
- end
88
- end
89
-
90
- test "passes observers to subclasses" do
91
- FooObserver.instance
92
- bar = Class.new(Foo)
93
- assert_equal Foo.observers_count, bar.observers_count
94
- end
95
- end
96
-
97
- class ObserverTest < ActiveModel::TestCase
98
- def setup
99
- ObservedModel.observers = :foo_observer
100
- FooObserver.singleton_class.instance_eval do
101
- alias_method :original_observed_classes, :observed_classes
102
- end
103
- end
104
-
105
- def teardown
106
- FooObserver.singleton_class.instance_eval do
107
- undef_method :observed_classes
108
- alias_method :observed_classes, :original_observed_classes
109
- end
110
- end
111
-
112
- test "guesses implicit observable model name" do
113
- assert_equal Foo, FooObserver.observed_class
114
- end
115
-
116
- test "tracks implicit observable models" do
117
- instance = FooObserver.new
118
- assert_equal [Foo], instance.observed_classes
119
- end
120
-
121
- test "tracks explicit observed model class" do
122
- FooObserver.observe ObservedModel
123
- instance = FooObserver.new
124
- assert_equal [ObservedModel], instance.observed_classes
125
- end
126
-
127
- test "tracks explicit observed model as string" do
128
- FooObserver.observe 'observed_model'
129
- instance = FooObserver.new
130
- assert_equal [ObservedModel], instance.observed_classes
131
- end
132
-
133
- test "tracks explicit observed model as symbol" do
134
- FooObserver.observe :observed_model
135
- instance = FooObserver.new
136
- assert_equal [ObservedModel], instance.observed_classes
137
- end
138
-
139
- test "calls existing observer event" do
140
- foo = Foo.new
141
- FooObserver.instance.stub = stub
142
- FooObserver.instance.stub.expects(:event_with).with(foo)
143
- Foo.notify_observers(:on_spec, foo)
144
- end
145
-
146
- test "calls existing observer event from the instance" do
147
- foo = Foo.new
148
- FooObserver.instance.stub = stub
149
- FooObserver.instance.stub.expects(:event_with).with(foo)
150
- foo.notify_observers(:on_spec)
151
- end
152
-
153
- test "passes extra arguments" do
154
- foo = Foo.new
155
- FooObserver.instance.stub = stub
156
- FooObserver.instance.stub.expects(:event_with).with(foo, :bar)
157
- Foo.send(:notify_observers, :on_spec, foo, :bar)
158
- end
159
-
160
- test "skips nonexistent observer event" do
161
- foo = Foo.new
162
- Foo.notify_observers(:whatever, foo)
163
- end
164
-
165
- test "update passes a block on to the observer" do
166
- yielded_value = nil
167
- FooObserver.instance.update(:around_save, Foo.new) do |val|
168
- yielded_value = val
169
- end
170
- assert_equal :in_around_save, yielded_value
171
- end
172
-
173
- test "observe redefines observed_classes class method" do
174
- class BarObserver < ActiveModel::Observer
175
- observe :foo
176
- end
177
-
178
- assert_equal [Foo], BarObserver.observed_classes
179
-
180
- BarObserver.observe(ObservedModel)
181
- assert_equal [ObservedModel], BarObserver.observed_classes
182
- end
183
- end