1 require 'abstract_unit'
4 include ActiveSupport::Callbacks
6 define_callbacks :before_save, :after_save
9 def callback_symbol(callback_method)
10 returning("#{callback_method}_method") do |method_name|
11 define_method(method_name) do
12 history << [callback_method, :symbol]
17 def callback_string(callback_method)
18 "history << [#{callback_method.to_sym.inspect}, :string]"
21 def callback_proc(callback_method)
22 Proc.new { |model| model.history << [callback_method, :proc] }
25 def callback_object(callback_method)
27 klass.send(:define_method, callback_method) do |model|
28 model.history << [callback_method, :object]
40 [:before_save, :after_save].each do |callback_method|
41 callback_method_sym = callback_method.to_sym
42 send(callback_method, callback_symbol(callback_method_sym))
43 send(callback_method, callback_string(callback_method_sym))
44 send(callback_method, callback_proc(callback_method_sym))
45 send(callback_method, callback_object(callback_method_sym))
46 send(callback_method) { |model| model.history << [callback_method_sym, :block] }
50 run_callbacks(:before_save)
51 run_callbacks(:after_save)
55 class ConditionalPerson < Record
57 before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true }
58 before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false }
59 before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false }
60 before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true }
62 before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes
63 before_save Proc.new { |r| r.history << "b00m" }, :if => :no
64 before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no
65 before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes
67 before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes'
68 before_save Proc.new { |r| r.history << "b00m" }, :if => 'no'
69 before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no'
70 before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes'
71 # Array with conditions
72 before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :if => [:yes, :other_yes]
73 before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, :no]
74 before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :unless => [:no, :other_no]
75 before_save Proc.new { |r| r.history << "b00m" }, :unless => [:yes, :no]
76 # Combined if and unless
77 before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no
78 before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes
79 # Array with different types of conditions
80 before_save Proc.new { |r| r.history << [:before_save, :symbol_proc_string_array] }, :if => [:yes, Proc.new { |r| true }, 'yes']
81 before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no']
82 # Array with different types of conditions comibned if and unless
83 before_save Proc.new { |r| r.history << [:before_save, :combined_symbol_proc_string_array] },
84 :if => [:yes, Proc.new { |r| true }, 'yes'], :unless => [:no, 'no']
85 before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no'], :unless => [:no, 'no']
88 def other_yes; true; end
90 def other_no; false; end
93 run_callbacks(:before_save)
94 run_callbacks(:after_save)
98 class CallbacksTest < Test::Unit::TestCase
101 assert_equal [], person.history
104 [:before_save, :symbol],
105 [:before_save, :string],
106 [:before_save, :proc],
107 [:before_save, :object],
108 [:before_save, :block],
109 [:after_save, :symbol],
110 [:after_save, :string],
111 [:after_save, :proc],
112 [:after_save, :object],
113 [:after_save, :block]
118 class ConditionalCallbackTest < Test::Unit::TestCase
119 def test_save_conditional_person
120 person = ConditionalPerson.new
123 [:before_save, :proc],
124 [:before_save, :proc],
125 [:before_save, :symbol],
126 [:before_save, :symbol],
127 [:before_save, :string],
128 [:before_save, :string],
129 [:before_save, :symbol_array],
130 [:before_save, :symbol_array],
131 [:before_save, :combined_symbol],
132 [:before_save, :symbol_proc_string_array],
133 [:before_save, :combined_symbol_proc_string_array]
138 class CallbackTest < Test::Unit::TestCase
139 include ActiveSupport::Callbacks
142 callback = Callback.new(:before, :save, :identifier => :lifesaver)
143 assert callback.eql?(Callback.new(:before, :save, :identifier => :lifesaver))
144 assert callback.eql?(Callback.new(:before, :save))
145 assert callback.eql?(:lifesaver)
146 assert callback.eql?(:save)
147 assert !callback.eql?(Callback.new(:before, :destroy))
148 assert !callback.eql?(:destroy)
152 a = Callback.new(:before, :save)
153 assert_equal({}, a.options)
155 b.options[:unless] = :pigs_fly
156 assert_equal({:unless => :pigs_fly}, b.options)
157 assert_equal({}, a.options)
161 class CallbackChainTest < Test::Unit::TestCase
162 include ActiveSupport::Callbacks
165 @chain = CallbackChain.build(:make, :bacon, :lettuce, :tomato)
169 assert_equal 3, @chain.size
170 assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method)
174 assert_equal :bacon, @chain.find(:bacon).method
177 def test_replace_or_append
178 assert_equal [:bacon, :lettuce, :tomato], (@chain.replace_or_append!(Callback.new(:make, :bacon))).map(&:method)
179 assert_equal [:bacon, :lettuce, :tomato, :turkey], (@chain.replace_or_append!(Callback.new(:make, :turkey))).map(&:method)
180 assert_equal [:bacon, :lettuce, :tomato, :turkey, :mayo], (@chain.replace_or_append!(Callback.new(:make, :mayo))).map(&:method)
184 assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method)
185 @chain.delete(:bacon)
186 assert_equal [:lettuce, :tomato], @chain.map(&:method)