Updated README.rdoc again
[feedcatcher.git] / vendor / rails / activerecord / test / cases / callbacks_test.rb
1 require "cases/helper"
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
125 attr_reader :after_save_called, :after_create_called, :after_update_called, :after_destroy_called
126 attr_accessor :cancel_before_save, :cancel_before_create, :cancel_before_update, :cancel_before_destroy
127
128 def before_save; !@cancel_before_save; end
129 def before_create; !@cancel_before_create; end
130 def before_update; !@cancel_before_update; end
131 def before_destroy; !@cancel_before_destroy; end
132
133 def after_save; @after_save_called = true; end
134 def after_update; @after_update_called = true; end
135 def after_create; @after_create_called = true; end
136 def after_destroy; @after_destroy_called = true; end
137 end
138
139 class CallbacksTest < ActiveRecord::TestCase
140 fixtures :developers
141
142 def test_initialize
143 david = CallbackDeveloper.new
144 assert_equal [
145 [ :after_initialize, :string ],
146 [ :after_initialize, :proc ],
147 [ :after_initialize, :object ],
148 [ :after_initialize, :block ],
149 ], david.history
150 end
151
152 def test_find
153 david = CallbackDeveloper.find(1)
154 assert_equal [
155 [ :after_find, :string ],
156 [ :after_find, :proc ],
157 [ :after_find, :object ],
158 [ :after_find, :block ],
159 [ :after_initialize, :string ],
160 [ :after_initialize, :proc ],
161 [ :after_initialize, :object ],
162 [ :after_initialize, :block ],
163 ], david.history
164 end
165
166 def test_new_valid?
167 david = CallbackDeveloper.new
168 david.valid?
169 assert_equal [
170 [ :after_initialize, :string ],
171 [ :after_initialize, :proc ],
172 [ :after_initialize, :object ],
173 [ :after_initialize, :block ],
174 [ :before_validation, :string ],
175 [ :before_validation, :proc ],
176 [ :before_validation, :object ],
177 [ :before_validation, :block ],
178 [ :before_validation_on_create, :string ],
179 [ :before_validation_on_create, :proc ],
180 [ :before_validation_on_create, :object ],
181 [ :before_validation_on_create, :block ],
182 [ :after_validation, :string ],
183 [ :after_validation, :proc ],
184 [ :after_validation, :object ],
185 [ :after_validation, :block ],
186 [ :after_validation_on_create, :string ],
187 [ :after_validation_on_create, :proc ],
188 [ :after_validation_on_create, :object ],
189 [ :after_validation_on_create, :block ]
190 ], david.history
191 end
192
193 def test_existing_valid?
194 david = CallbackDeveloper.find(1)
195 david.valid?
196 assert_equal [
197 [ :after_find, :string ],
198 [ :after_find, :proc ],
199 [ :after_find, :object ],
200 [ :after_find, :block ],
201 [ :after_initialize, :string ],
202 [ :after_initialize, :proc ],
203 [ :after_initialize, :object ],
204 [ :after_initialize, :block ],
205 [ :before_validation, :string ],
206 [ :before_validation, :proc ],
207 [ :before_validation, :object ],
208 [ :before_validation, :block ],
209 [ :before_validation_on_update, :string ],
210 [ :before_validation_on_update, :proc ],
211 [ :before_validation_on_update, :object ],
212 [ :before_validation_on_update, :block ],
213 [ :after_validation, :string ],
214 [ :after_validation, :proc ],
215 [ :after_validation, :object ],
216 [ :after_validation, :block ],
217 [ :after_validation_on_update, :string ],
218 [ :after_validation_on_update, :proc ],
219 [ :after_validation_on_update, :object ],
220 [ :after_validation_on_update, :block ]
221 ], david.history
222 end
223
224 def test_create
225 david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
226 assert_equal [
227 [ :after_initialize, :string ],
228 [ :after_initialize, :proc ],
229 [ :after_initialize, :object ],
230 [ :after_initialize, :block ],
231 [ :before_validation, :string ],
232 [ :before_validation, :proc ],
233 [ :before_validation, :object ],
234 [ :before_validation, :block ],
235 [ :before_validation_on_create, :string ],
236 [ :before_validation_on_create, :proc ],
237 [ :before_validation_on_create, :object ],
238 [ :before_validation_on_create, :block ],
239 [ :after_validation, :string ],
240 [ :after_validation, :proc ],
241 [ :after_validation, :object ],
242 [ :after_validation, :block ],
243 [ :after_validation_on_create, :string ],
244 [ :after_validation_on_create, :proc ],
245 [ :after_validation_on_create, :object ],
246 [ :after_validation_on_create, :block ],
247 [ :before_save, :string ],
248 [ :before_save, :proc ],
249 [ :before_save, :object ],
250 [ :before_save, :block ],
251 [ :before_create, :string ],
252 [ :before_create, :proc ],
253 [ :before_create, :object ],
254 [ :before_create, :block ],
255 [ :after_create, :string ],
256 [ :after_create, :proc ],
257 [ :after_create, :object ],
258 [ :after_create, :block ],
259 [ :after_save, :string ],
260 [ :after_save, :proc ],
261 [ :after_save, :object ],
262 [ :after_save, :block ]
263 ], david.history
264 end
265
266 def test_save
267 david = CallbackDeveloper.find(1)
268 david.save
269 assert_equal [
270 [ :after_find, :string ],
271 [ :after_find, :proc ],
272 [ :after_find, :object ],
273 [ :after_find, :block ],
274 [ :after_initialize, :string ],
275 [ :after_initialize, :proc ],
276 [ :after_initialize, :object ],
277 [ :after_initialize, :block ],
278 [ :before_validation, :string ],
279 [ :before_validation, :proc ],
280 [ :before_validation, :object ],
281 [ :before_validation, :block ],
282 [ :before_validation_on_update, :string ],
283 [ :before_validation_on_update, :proc ],
284 [ :before_validation_on_update, :object ],
285 [ :before_validation_on_update, :block ],
286 [ :after_validation, :string ],
287 [ :after_validation, :proc ],
288 [ :after_validation, :object ],
289 [ :after_validation, :block ],
290 [ :after_validation_on_update, :string ],
291 [ :after_validation_on_update, :proc ],
292 [ :after_validation_on_update, :object ],
293 [ :after_validation_on_update, :block ],
294 [ :before_save, :string ],
295 [ :before_save, :proc ],
296 [ :before_save, :object ],
297 [ :before_save, :block ],
298 [ :before_update, :string ],
299 [ :before_update, :proc ],
300 [ :before_update, :object ],
301 [ :before_update, :block ],
302 [ :after_update, :string ],
303 [ :after_update, :proc ],
304 [ :after_update, :object ],
305 [ :after_update, :block ],
306 [ :after_save, :string ],
307 [ :after_save, :proc ],
308 [ :after_save, :object ],
309 [ :after_save, :block ]
310 ], david.history
311 end
312
313 def test_destroy
314 david = CallbackDeveloper.find(1)
315 david.destroy
316 assert_equal [
317 [ :after_find, :string ],
318 [ :after_find, :proc ],
319 [ :after_find, :object ],
320 [ :after_find, :block ],
321 [ :after_initialize, :string ],
322 [ :after_initialize, :proc ],
323 [ :after_initialize, :object ],
324 [ :after_initialize, :block ],
325 [ :before_destroy, :string ],
326 [ :before_destroy, :proc ],
327 [ :before_destroy, :object ],
328 [ :before_destroy, :block ],
329 [ :after_destroy, :string ],
330 [ :after_destroy, :proc ],
331 [ :after_destroy, :object ],
332 [ :after_destroy, :block ]
333 ], david.history
334 end
335
336 def test_delete
337 david = CallbackDeveloper.find(1)
338 CallbackDeveloper.delete(david.id)
339 assert_equal [
340 [ :after_find, :string ],
341 [ :after_find, :proc ],
342 [ :after_find, :object ],
343 [ :after_find, :block ],
344 [ :after_initialize, :string ],
345 [ :after_initialize, :proc ],
346 [ :after_initialize, :object ],
347 [ :after_initialize, :block ],
348 ], david.history
349 end
350
351 def test_before_save_returning_false
352 david = ImmutableDeveloper.find(1)
353 assert david.valid?
354 assert !david.save
355 assert_raise(ActiveRecord::RecordNotSaved) { david.save! }
356
357 david = ImmutableDeveloper.find(1)
358 david.salary = 10_000_000
359 assert !david.valid?
360 assert !david.save
361 assert_raise(ActiveRecord::RecordInvalid) { david.save! }
362
363 someone = CallbackCancellationDeveloper.find(1)
364 someone.cancel_before_save = true
365 assert someone.valid?
366 assert !someone.save
367 assert_save_callbacks_not_called(someone)
368 end
369
370 def test_before_create_returning_false
371 someone = CallbackCancellationDeveloper.new
372 someone.cancel_before_create = true
373 assert someone.valid?
374 assert !someone.save
375 assert_save_callbacks_not_called(someone)
376 end
377
378 def test_before_update_returning_false
379 someone = CallbackCancellationDeveloper.find(1)
380 someone.cancel_before_update = true
381 assert someone.valid?
382 assert !someone.save
383 assert_save_callbacks_not_called(someone)
384 end
385
386 def test_before_destroy_returning_false
387 david = ImmutableDeveloper.find(1)
388 assert !david.destroy
389 assert_not_nil ImmutableDeveloper.find_by_id(1)
390
391 someone = CallbackCancellationDeveloper.find(1)
392 someone.cancel_before_destroy = true
393 assert !someone.destroy
394 assert !someone.after_destroy_called
395 end
396
397 def assert_save_callbacks_not_called(someone)
398 assert !someone.after_save_called
399 assert !someone.after_create_called
400 assert !someone.after_update_called
401 end
402 private :assert_save_callbacks_not_called
403
404 def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
405 david = CallbackDeveloper.find(1)
406 CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
407 CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
408 david.save
409 assert_equal [
410 [ :after_find, :string ],
411 [ :after_find, :proc ],
412 [ :after_find, :object ],
413 [ :after_find, :block ],
414 [ :after_initialize, :string ],
415 [ :after_initialize, :proc ],
416 [ :after_initialize, :object ],
417 [ :after_initialize, :block ],
418 [ :before_validation, :string ],
419 [ :before_validation, :proc ],
420 [ :before_validation, :object ],
421 [ :before_validation, :block ],
422 [ :before_validation, :returning_false ]
423 ], david.history
424 end
425
426 def test_inheritence_of_callbacks
427 parent = ParentDeveloper.new
428 assert !parent.after_save_called
429 parent.save
430 assert parent.after_save_called
431
432 child = ChildDeveloper.new
433 assert !child.after_save_called
434 child.save
435 assert child.after_save_called
436 end
437
438 end