Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/branches/2-1-caching/activerecord/test/callbacks_test.rb

Revision 6026, 13.1 kB (checked in by rick, 2 years ago)

Add missing tests ensuring callbacks work with class inheritance. Closes #7339 [sandofsky]

Line 
1 require 'abstract_unit'
2
3 class CallbackDeveloper < ActiveRecord::Base
4   set_table_name 'developers'
5
6   class << self
7     def callback_string(callback_method)
8       "history << [#{callback_method.to_sym.inspect}, :string]"
9     end
10
11     def callback_proc(callback_method)
12       Proc.new { |model| model.history << [callback_method, :proc] }
13     end
14
15     def define_callback_method(callback_method)
16       define_method("#{callback_method}_method") do |model|
17         model.history << [callback_method, :method]
18       end
19     end
20
21     def callback_object(callback_method)
22       klass = Class.new
23       klass.send(:define_method, callback_method) do |model|
24         model.history << [callback_method, :object]
25       end
26       klass.new
27     end
28   end
29
30   ActiveRecord::Callbacks::CALLBACKS.each do |callback_method|
31     callback_method_sym = callback_method.to_sym
32     define_callback_method(callback_method_sym)
33     send(callback_method, callback_method_sym)
34     send(callback_method, callback_string(callback_method_sym))
35     send(callback_method, callback_proc(callback_method_sym))
36     send(callback_method, callback_object(callback_method_sym))
37     send(callback_method) { |model| model.history << [callback_method_sym, :block] }
38   end
39
40   def history
41     @history ||= []
42   end
43
44   # after_initialize and after_find are invoked only if instance methods have been defined.
45   def after_initialize
46   end
47
48   def after_find
49   end
50 end
51
52 class ParentDeveloper < ActiveRecord::Base
53   set_table_name 'developers'
54   attr_accessor :after_save_called
55   before_validation {|record| record.after_save_called = true}
56 end
57
58 class ChildDeveloper < ParentDeveloper
59  
60 end
61
62 class RecursiveCallbackDeveloper < ActiveRecord::Base
63   set_table_name 'developers'
64
65   before_save :on_before_save
66   after_save :on_after_save
67
68   attr_reader :on_before_save_called, :on_after_save_called
69
70   def on_before_save
71     @on_before_save_called ||= 0
72     @on_before_save_called += 1
73     save unless @on_before_save_called > 1
74   end
75
76   def on_after_save
77     @on_after_save_called ||= 0
78     @on_after_save_called += 1
79     save unless @on_after_save_called > 1
80   end
81 end
82
83 class ImmutableDeveloper < ActiveRecord::Base
84   set_table_name 'developers'
85
86   validates_inclusion_of :salary, :in => 50000..200000
87
88   before_save :cancel
89   before_destroy :cancel
90
91   def cancelled?
92     @cancelled == true
93   end
94
95   private
96     def cancel
97       @cancelled = true
98       false
99     end
100 end
101
102 class ImmutableMethodDeveloper < ActiveRecord::Base
103   set_table_name 'developers'
104
105   validates_inclusion_of :salary, :in => 50000..200000
106
107   def cancelled?
108     @cancelled == true
109   end
110
111   def before_save
112     @cancelled = true
113     false
114   end
115
116   def before_destroy
117     @cancelled = true
118     false
119   end
120 end
121
122 class CallbackCancellationDeveloper < ActiveRecord::Base
123   set_table_name 'developers'
124   def before_create
125     false
126   end
127 end
128
129 class CallbacksTest < Test::Unit::TestCase
130   fixtures :developers
131
132   def test_initialize
133     david = CallbackDeveloper.new
134     assert_equal [
135       [ :after_initialize,            :string ],
136       [ :after_initialize,            :proc   ],
137       [ :after_initialize,            :object ],
138       [ :after_initialize,            :block  ],
139     ], david.history
140   end
141
142   def test_find
143     david = CallbackDeveloper.find(1)
144     assert_equal [
145       [ :after_find,            :string ],
146       [ :after_find,            :proc   ],
147       [ :after_find,            :object ],
148       [ :after_find,            :block  ],
149       [ :after_initialize,            :string ],
150       [ :after_initialize,            :proc   ],
151       [ :after_initialize,            :object ],
152       [ :after_initialize,            :block  ],
153     ], david.history
154   end
155
156   def test_new_valid?
157     david = CallbackDeveloper.new
158     david.valid?
159     assert_equal [
160       [ :after_initialize,            :string ],
161       [ :after_initialize,            :proc   ],
162       [ :after_initialize,            :object ],
163       [ :after_initialize,            :block  ],
164       [ :before_validation,           :string ],
165       [ :before_validation,           :proc   ],
166       [ :before_validation,           :object ],
167       [ :before_validation,           :block  ],
168       [ :before_validation_on_create, :string ],
169       [ :before_validation_on_create, :proc   ],
170       [ :before_validation_on_create, :object ],
171       [ :before_validation_on_create, :block  ],
172       [ :after_validation,            :string ],
173       [ :after_validation,            :proc   ],
174       [ :after_validation,            :object ],
175       [ :after_validation,            :block  ],
176       [ :after_validation_on_create,  :string ],
177       [ :after_validation_on_create,  :proc   ],
178       [ :after_validation_on_create,  :object ],
179       [ :after_validation_on_create,  :block  ]
180     ], david.history
181   end
182
183   def test_existing_valid?
184     david = CallbackDeveloper.find(1)
185     david.valid?
186     assert_equal [
187       [ :after_find,            :string ],
188       [ :after_find,            :proc   ],
189       [ :after_find,            :object ],
190       [ :after_find,            :block  ],
191       [ :after_initialize,            :string ],
192       [ :after_initialize,            :proc   ],
193       [ :after_initialize,            :object ],
194       [ :after_initialize,            :block  ],
195       [ :before_validation,           :string ],
196       [ :before_validation,           :proc   ],
197       [ :before_validation,           :object ],
198       [ :before_validation,           :block  ],
199       [ :before_validation_on_update, :string ],
200       [ :before_validation_on_update, :proc   ],
201       [ :before_validation_on_update, :object ],
202       [ :before_validation_on_update, :block  ],
203       [ :after_validation,            :string ],
204       [ :after_validation,            :proc   ],
205       [ :after_validation,            :object ],
206       [ :after_validation,            :block  ],
207       [ :after_validation_on_update,  :string ],
208       [ :after_validation_on_update,  :proc   ],
209       [ :after_validation_on_update,  :object ],
210       [ :after_validation_on_update,  :block  ]
211     ], david.history
212   end
213
214   def test_create
215     david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
216     assert_equal [
217       [ :after_initialize,            :string ],
218       [ :after_initialize,            :proc   ],
219       [ :after_initialize,            :object ],
220       [ :after_initialize,            :block  ],
221       [ :before_validation,           :string ],
222       [ :before_validation,           :proc   ],
223       [ :before_validation,           :object ],
224       [ :before_validation,           :block  ],
225       [ :before_validation_on_create, :string ],
226       [ :before_validation_on_create, :proc   ],
227       [ :before_validation_on_create, :object ],
228       [ :before_validation_on_create, :block  ],
229       [ :after_validation,            :string ],
230       [ :after_validation,            :proc   ],
231       [ :after_validation,            :object ],
232       [ :after_validation,            :block  ],
233       [ :after_validation_on_create,  :string ],
234       [ :after_validation_on_create,  :proc   ],
235       [ :after_validation_on_create,  :object ],
236       [ :after_validation_on_create,  :block  ],
237       [ :before_save,                 :string ],
238       [ :before_save,                 :proc   ],
239       [ :before_save,                 :object ],
240       [ :before_save,                 :block  ],
241       [ :before_create,               :string ],
242       [ :before_create,               :proc   ],
243       [ :before_create,               :object ],
244       [ :before_create,               :block  ],
245       [ :after_create,                :string ],
246       [ :after_create,                :proc   ],
247       [ :after_create,                :object ],
248       [ :after_create,                :block  ],
249       [ :after_save,                  :string ],
250       [ :after_save,                  :proc   ],
251       [ :after_save,                  :object ],
252       [ :after_save,                  :block  ]
253     ], david.history
254   end
255
256   def test_save
257     david = CallbackDeveloper.find(1)
258     david.save
259     assert_equal [
260       [ :after_find,            :string ],
261       [ :after_find,            :proc   ],
262       [ :after_find,            :object ],
263       [ :after_find,            :block  ],
264       [ :after_initialize,            :string ],
265       [ :after_initialize,            :proc   ],
266       [ :after_initialize,            :object ],
267       [ :after_initialize,            :block  ],
268       [ :before_validation,           :string ],
269       [ :before_validation,           :proc   ],
270       [ :before_validation,           :object ],
271       [ :before_validation,           :block  ],
272       [ :before_validation_on_update, :string ],
273       [ :before_validation_on_update, :proc   ],
274       [ :before_validation_on_update, :object ],
275       [ :before_validation_on_update, :block  ],
276       [ :after_validation,            :string ],
277       [ :after_validation,            :proc   ],
278       [ :after_validation,            :object ],
279       [ :after_validation,            :block  ],
280       [ :after_validation_on_update,  :string ],
281       [ :after_validation_on_update,  :proc   ],
282       [ :after_validation_on_update,  :object ],
283       [ :after_validation_on_update,  :block  ],
284       [ :before_save,                 :string ],
285       [ :before_save,                 :proc   ],
286       [ :before_save,                 :object ],
287       [ :before_save,                 :block  ],
288       [ :before_update,               :string ],
289       [ :before_update,               :proc   ],
290       [ :before_update,               :object ],
291       [ :before_update,               :block  ],
292       [ :after_update,                :string ],
293       [ :after_update,                :proc   ],
294       [ :after_update,                :object ],
295       [ :after_update,                :block  ],
296       [ :after_save,                  :string ],
297       [ :after_save,                  :proc   ],
298       [ :after_save,                  :object ],
299       [ :after_save,                  :block  ]
300     ], david.history
301   end
302
303   def test_destroy
304     david = CallbackDeveloper.find(1)
305     david.destroy
306     assert_equal [
307       [ :after_find,            :string ],
308       [ :after_find,            :proc   ],
309       [ :after_find,            :object ],
310       [ :after_find,            :block  ],
311       [ :after_initialize,            :string ],
312       [ :after_initialize,            :proc   ],
313       [ :after_initialize,            :object ],
314       [ :after_initialize,            :block  ],
315       [ :before_destroy,              :string ],
316       [ :before_destroy,              :proc   ],
317       [ :before_destroy,              :object ],
318       [ :before_destroy,              :block  ],
319       [ :after_destroy,               :string ],
320       [ :after_destroy,               :proc   ],
321       [ :after_destroy,               :object ],
322       [ :after_destroy,               :block  ]
323     ], david.history
324   end
325
326   def test_delete
327     david = CallbackDeveloper.find(1)
328     CallbackDeveloper.delete(david.id)
329     assert_equal [
330       [ :after_find,            :string ],
331       [ :after_find,            :proc   ],
332       [ :after_find,            :object ],
333       [ :after_find,            :block  ],
334       [ :after_initialize,            :string ],
335       [ :after_initialize,            :proc   ],
336       [ :after_initialize,            :object ],
337       [ :after_initialize,            :block  ],
338     ], david.history
339   end
340
341   def test_before_save_returning_false
342     david = ImmutableDeveloper.find(1)
343     assert david.valid?
344     assert !david.save
345     assert_raises(ActiveRecord::RecordNotSaved) { david.save! }
346
347     david = ImmutableDeveloper.find(1)
348     david.salary = 10_000_000
349     assert !david.valid?
350     assert !david.save
351     assert_raises(ActiveRecord::RecordInvalid) { david.save! }
352   end
353
354   def test_before_create_returning_false
355     someone = CallbackCancellationDeveloper.new
356     assert someone.valid?
357     assert !someone.save
358   end
359
360   def test_before_destroy_returning_false
361     david = ImmutableDeveloper.find(1)
362     assert !david.destroy
363     assert_not_nil ImmutableDeveloper.find_by_id(1)
364   end 
365
366   def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
367     david = CallbackDeveloper.find(1)
368     CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
369     CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
370     david.save
371     assert_equal [
372       [ :after_find,            :string ],
373       [ :after_find,            :proc   ],
374       [ :after_find,            :object ],
375       [ :after_find,            :block  ],
376       [ :after_initialize,            :string ],
377       [ :after_initialize,            :proc   ],
378       [ :after_initialize,            :object ],
379       [ :after_initialize,            :block  ],
380       [ :before_validation,           :string ],
381       [ :before_validation,           :proc   ],
382       [ :before_validation,           :object ],
383       [ :before_validation,           :block  ],
384       [ :before_validation, :returning_false  ]
385     ], david.history
386   end
387  
388   def test_inheritence_of_callbacks
389     parent = ParentDeveloper.new
390     assert !parent.after_save_called
391     parent.save
392     assert parent.after_save_called
393    
394     child = ChildDeveloper.new
395     assert !child.after_save_called
396     child.save
397     assert child.after_save_called
398   end
399  
400 end
Note: See TracBrowser for help on using the browser.