aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test/callbacks_test.rb
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-10-12 22:15:43 -0500
committerJoshua Peek <josh@joshpeek.com>2009-10-12 22:15:43 -0500
commit21e7b8462113fc7c0fd1882dcc2bf7225de67b1a (patch)
tree81350780f50b8378aec99210d956bba3dda635f7 /activesupport/test/callbacks_test.rb
parent9bc8defe38253840ceb9c4ad92e7c3abc0066ed8 (diff)
downloadrails-21e7b8462113fc7c0fd1882dcc2bf7225de67b1a.tar.gz
rails-21e7b8462113fc7c0fd1882dcc2bf7225de67b1a.tar.bz2
rails-21e7b8462113fc7c0fd1882dcc2bf7225de67b1a.zip
Callbacks, DeprecatedCallbacks = NewCallbacks, Callbacks
Diffstat (limited to 'activesupport/test/callbacks_test.rb')
-rw-r--r--activesupport/test/callbacks_test.rb632
1 files changed, 486 insertions, 146 deletions
diff --git a/activesupport/test/callbacks_test.rb b/activesupport/test/callbacks_test.rb
index 2f747e2238..df98644436 100644
--- a/activesupport/test/callbacks_test.rb
+++ b/activesupport/test/callbacks_test.rb
@@ -1,188 +1,528 @@
-require 'abstract_unit'
+# require 'abstract_unit'
+require 'test/unit'
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'active_support'
-class Record
- include ActiveSupport::Callbacks
+module CallbacksTest
+ class Record
+ include ActiveSupport::Callbacks
- define_callbacks :before_save, :after_save
+ define_callbacks :save
- class << self
- def callback_symbol(callback_method)
- method_name = "#{callback_method}_method"
- define_method(method_name) do
- history << [callback_method, :symbol]
+ def self.before_save(*filters, &blk)
+ set_callback(:save, :before, *filters, &blk)
+ end
+
+ def self.after_save(*filters, &blk)
+ set_callback(:save, :after, *filters, &blk)
+ end
+
+ class << self
+ def callback_symbol(callback_method)
+ method_name = :"#{callback_method}_method"
+ define_method(method_name) do
+ history << [callback_method, :symbol]
+ end
+ method_name
+ end
+
+ def callback_string(callback_method)
+ "history << [#{callback_method.to_sym.inspect}, :string]"
+ end
+
+ def callback_proc(callback_method)
+ Proc.new { |model| model.history << [callback_method, :proc] }
+ end
+
+ def callback_object(callback_method)
+ klass = Class.new
+ klass.send(:define_method, callback_method) do |model|
+ model.history << [:"#{callback_method}_save", :object]
+ end
+ klass.new
end
- method_name
end
- def callback_string(callback_method)
- "history << [#{callback_method.to_sym.inspect}, :string]"
+ def history
+ @history ||= []
+ end
+ end
+
+ class Person < Record
+ [:before_save, :after_save].each do |callback_method|
+ callback_method_sym = callback_method.to_sym
+ send(callback_method, callback_symbol(callback_method_sym))
+ send(callback_method, callback_string(callback_method_sym))
+ send(callback_method, callback_proc(callback_method_sym))
+ send(callback_method, callback_object(callback_method_sym.to_s.gsub(/_save/, '')))
+ send(callback_method) { |model| model.history << [callback_method_sym, :block] }
end
- def callback_proc(callback_method)
- Proc.new { |model| model.history << [callback_method, :proc] }
+ def save
+ run_callbacks :save
end
+ end
+
+ class PersonSkipper < Person
+ skip_callback :save, :before, :before_save_method, :if => :yes
+ skip_callback :save, :after, :before_save_method, :unless => :yes
+ skip_callback :save, :after, :before_save_method, :if => :no
+ skip_callback :save, :before, :before_save_method, :unless => :no
+ def yes; true; end
+ def no; false; end
+ end
+
+ class ParentController
+ include ActiveSupport::Callbacks
+
+ define_callbacks :dispatch
+
+ set_callback :dispatch, :before, :log, :per_key => {:unless => proc {|c| c.action_name == :index || c.action_name == :show }}
+ set_callback :dispatch, :after, :log2
- def callback_object(callback_method)
- klass = Class.new
- klass.send(:define_method, callback_method) do |model|
- model.history << [callback_method, :object]
+ attr_reader :action_name, :logger
+ def initialize(action_name)
+ @action_name, @logger = action_name, []
+ end
+
+ def log
+ @logger << action_name
+ end
+
+ def log2
+ @logger << action_name
+ end
+
+ def dispatch
+ run_callbacks :dispatch, action_name do
+ @logger << "Done"
end
- klass.new
+ self
end
end
- def history
- @history ||= []
+ class Child < ParentController
+ skip_callback :dispatch, :before, :log, :per_key => {:if => proc {|c| c.action_name == :update} }
+ skip_callback :dispatch, :after, :log2
end
-end
-class Person < Record
- [:before_save, :after_save].each do |callback_method|
- callback_method_sym = callback_method.to_sym
- send(callback_method, callback_symbol(callback_method_sym))
- send(callback_method, callback_string(callback_method_sym))
- send(callback_method, callback_proc(callback_method_sym))
- send(callback_method, callback_object(callback_method_sym))
- send(callback_method) { |model| model.history << [callback_method_sym, :block] }
+ class OneTimeCompile < Record
+ @@starts_true, @@starts_false = true, false
+
+ def initialize
+ super
+ end
+
+ before_save Proc.new {|r| r.history << [:before_save, :starts_true, :if] }, :per_key => {:if => :starts_true}
+ before_save Proc.new {|r| r.history << [:before_save, :starts_false, :if] }, :per_key => {:if => :starts_false}
+ before_save Proc.new {|r| r.history << [:before_save, :starts_true, :unless] }, :per_key => {:unless => :starts_true}
+ before_save Proc.new {|r| r.history << [:before_save, :starts_false, :unless] }, :per_key => {:unless => :starts_false}
+
+ def starts_true
+ if @@starts_true
+ @@starts_true = false
+ return true
+ end
+ @@starts_true
+ end
+
+ def starts_false
+ unless @@starts_false
+ @@starts_false = true
+ return false
+ end
+ @@starts_false
+ end
+
+ def save
+ run_callbacks :save, :action
+ end
end
- def save
- run_callbacks(:before_save)
- run_callbacks(:after_save)
+ class OneTimeCompileTest < Test::Unit::TestCase
+ def test_optimized_first_compile
+ around = OneTimeCompile.new
+ around.save
+ assert_equal [
+ [:before_save, :starts_true, :if],
+ [:before_save, :starts_true, :unless]
+ ], around.history
+ end
end
-end
-class ConditionalPerson < Record
- # proc
- before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true }
- before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false }
- before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false }
- before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true }
- # symbol
- before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes
- before_save Proc.new { |r| r.history << "b00m" }, :if => :no
- before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no
- before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes
- # string
- before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes'
- before_save Proc.new { |r| r.history << "b00m" }, :if => 'no'
- before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no'
- before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes'
- # Array with conditions
- before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :if => [:yes, :other_yes]
- before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, :no]
- before_save Proc.new { |r| r.history << [:before_save, :symbol_array] }, :unless => [:no, :other_no]
- before_save Proc.new { |r| r.history << "b00m" }, :unless => [:yes, :no]
- # Combined if and unless
- before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no
- before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes
- # Array with different types of conditions
- before_save Proc.new { |r| r.history << [:before_save, :symbol_proc_string_array] }, :if => [:yes, Proc.new { |r| true }, 'yes']
- before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no']
- # Array with different types of conditions comibned if and unless
- before_save Proc.new { |r| r.history << [:before_save, :combined_symbol_proc_string_array] },
- :if => [:yes, Proc.new { |r| true }, 'yes'], :unless => [:no, 'no']
- before_save Proc.new { |r| r.history << "b00m" }, :if => [:yes, Proc.new { |r| true }, 'no'], :unless => [:no, 'no']
-
- def yes; true; end
- def other_yes; true; end
- def no; false; end
- def other_no; false; end
-
- def save
- run_callbacks(:before_save)
- run_callbacks(:after_save)
+ class ConditionalPerson < Record
+ # proc
+ before_save Proc.new { |r| r.history << [:before_save, :proc] }, :if => Proc.new { |r| true }
+ before_save Proc.new { |r| r.history << "b00m" }, :if => Proc.new { |r| false }
+ before_save Proc.new { |r| r.history << [:before_save, :proc] }, :unless => Proc.new { |r| false }
+ before_save Proc.new { |r| r.history << "b00m" }, :unless => Proc.new { |r| true }
+ # symbol
+ before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :if => :yes
+ before_save Proc.new { |r| r.history << "b00m" }, :if => :no
+ before_save Proc.new { |r| r.history << [:before_save, :symbol] }, :unless => :no
+ before_save Proc.new { |r| r.history << "b00m" }, :unless => :yes
+ # string
+ before_save Proc.new { |r| r.history << [:before_save, :string] }, :if => 'yes'
+ before_save Proc.new { |r| r.history << "b00m" }, :if => 'no'
+ before_save Proc.new { |r| r.history << [:before_save, :string] }, :unless => 'no'
+ before_save Proc.new { |r| r.history << "b00m" }, :unless => 'yes'
+ # Combined if and unless
+ before_save Proc.new { |r| r.history << [:before_save, :combined_symbol] }, :if => :yes, :unless => :no
+ before_save Proc.new { |r| r.history << "b00m" }, :if => :yes, :unless => :yes
+
+ def yes; true; end
+ def other_yes; true; end
+ def no; false; end
+ def other_no; false; end
+
+ def save
+ run_callbacks :save
+ end
end
-end
-class CallbacksTest < Test::Unit::TestCase
- def test_save_person
- person = Person.new
- assert_equal [], person.history
- person.save
- assert_equal [
- [:before_save, :symbol],
- [:before_save, :string],
- [:before_save, :proc],
- [:before_save, :object],
- [:before_save, :block],
- [:after_save, :symbol],
- [:after_save, :string],
- [:after_save, :proc],
- [:after_save, :object],
- [:after_save, :block]
- ], person.history
+ class CleanPerson < ConditionalPerson
+ reset_callbacks :save
end
-end
-class ConditionalCallbackTest < Test::Unit::TestCase
- def test_save_conditional_person
- person = ConditionalPerson.new
- person.save
- assert_equal [
- [:before_save, :proc],
- [:before_save, :proc],
- [:before_save, :symbol],
- [:before_save, :symbol],
- [:before_save, :string],
- [:before_save, :string],
- [:before_save, :symbol_array],
- [:before_save, :symbol_array],
- [:before_save, :combined_symbol],
- [:before_save, :symbol_proc_string_array],
- [:before_save, :combined_symbol_proc_string_array]
- ], person.history
+ class MySuper
+ include ActiveSupport::Callbacks
+ define_callbacks :save
end
-end
-class CallbackTest < Test::Unit::TestCase
- include ActiveSupport::Callbacks
+ class AroundPerson < MySuper
+ attr_reader :history
+
+ set_callback :save, :before, :nope, :if => :no
+ set_callback :save, :before, :nope, :unless => :yes
+ set_callback :save, :after, :tweedle
+ set_callback :save, :before, "tweedle_dee"
+ set_callback :save, :before, proc {|m| m.history << "yup" }
+ set_callback :save, :before, :nope, :if => proc { false }
+ set_callback :save, :before, :nope, :unless => proc { true }
+ set_callback :save, :before, :yup, :if => proc { true }
+ set_callback :save, :before, :yup, :unless => proc { false }
+ set_callback :save, :around, :tweedle_dum
+ set_callback :save, :around, :w0tyes, :if => :yes
+ set_callback :save, :around, :w0tno, :if => :no
+ set_callback :save, :around, :tweedle_deedle
+
+ def no; false; end
+ def yes; true; end
+
+ def nope
+ @history << "boom"
+ end
+
+ def yup
+ @history << "yup"
+ end
+
+ def w0tyes
+ @history << "w0tyes before"
+ yield
+ @history << "w0tyes after"
+ end
+
+ def w0tno
+ @history << "boom"
+ yield
+ end
+
+ def tweedle_dee
+ @history << "tweedle dee"
+ end
+
+ def tweedle_dum
+ @history << "tweedle dum pre"
+ yield
+ @history << "tweedle dum post"
+ end
+
+ def tweedle
+ @history << "tweedle"
+ end
+
+ def tweedle_deedle
+ @history << "tweedle deedle pre"
+ yield
+ @history << "tweedle deedle post"
+ end
+
+ def initialize
+ @history = []
+ end
- def test_eql
- callback = Callback.new(:before, :save, :identifier => :lifesaver)
- assert callback.eql?(Callback.new(:before, :save, :identifier => :lifesaver))
- assert callback.eql?(Callback.new(:before, :save))
- assert callback.eql?(:lifesaver)
- assert callback.eql?(:save)
- assert !callback.eql?(Callback.new(:before, :destroy))
- assert !callback.eql?(:destroy)
+ def save
+ run_callbacks :save do
+ @history << "running"
+ end
+ end
end
- def test_dup
- a = Callback.new(:before, :save)
- assert_equal({}, a.options)
- b = a.dup
- b.options[:unless] = :pigs_fly
- assert_equal({:unless => :pigs_fly}, b.options)
- assert_equal({}, a.options)
+ class HyphenatedCallbacks
+ include ActiveSupport::Callbacks
+ define_callbacks :save
+ attr_reader :stuff
+
+ set_callback :save, :before, :omg, :per_key => {:if => :yes}
+
+ def yes() true end
+
+ def omg
+ @stuff = "OMG"
+ end
+
+ def save
+ run_callbacks :save, "hyphen-ated" do
+ @stuff
+ end
+ end
+ end
+
+ class AroundCallbacksTest < Test::Unit::TestCase
+ def test_save_around
+ around = AroundPerson.new
+ around.save
+ assert_equal [
+ "tweedle dee",
+ "yup", "yup",
+ "tweedle dum pre",
+ "w0tyes before",
+ "tweedle deedle pre",
+ "running",
+ "tweedle deedle post",
+ "w0tyes after",
+ "tweedle dum post",
+ "tweedle"
+ ], around.history
+ end
+ end
+
+ class SkipCallbacksTest < Test::Unit::TestCase
+ def test_skip_person
+ person = PersonSkipper.new
+ assert_equal [], person.history
+ person.save
+ assert_equal [
+ [:before_save, :string],
+ [:before_save, :proc],
+ [:before_save, :object],
+ [:before_save, :block],
+ [:after_save, :block],
+ [:after_save, :object],
+ [:after_save, :proc],
+ [:after_save, :string],
+ [:after_save, :symbol]
+ ], person.history
+ end
+ end
+
+ class CallbacksTest < Test::Unit::TestCase
+ def test_save_person
+ person = Person.new
+ assert_equal [], person.history
+ person.save
+ assert_equal [
+ [:before_save, :symbol],
+ [:before_save, :string],
+ [:before_save, :proc],
+ [:before_save, :object],
+ [:before_save, :block],
+ [:after_save, :block],
+ [:after_save, :object],
+ [:after_save, :proc],
+ [:after_save, :string],
+ [:after_save, :symbol]
+ ], person.history
+ end
+ end
+
+ class ConditionalCallbackTest < Test::Unit::TestCase
+ def test_save_conditional_person
+ person = ConditionalPerson.new
+ person.save
+ assert_equal [
+ [:before_save, :proc],
+ [:before_save, :proc],
+ [:before_save, :symbol],
+ [:before_save, :symbol],
+ [:before_save, :string],
+ [:before_save, :string],
+ [:before_save, :combined_symbol],
+ ], person.history
+ end
+ end
+
+ class ResetCallbackTest < Test::Unit::TestCase
+ def test_save_conditional_person
+ person = CleanPerson.new
+ person.save
+ assert_equal [], person.history
+ end
+ end
+
+ class CallbackTerminator
+ include ActiveSupport::Callbacks
+
+ define_callbacks :save, :terminator => "result == :halt"
+
+ set_callback :save, :before, :first
+ set_callback :save, :before, :second
+ set_callback :save, :around, :around_it
+ set_callback :save, :before, :third
+ set_callback :save, :after, :first
+ set_callback :save, :around, :around_it
+ set_callback :save, :after, :second
+ set_callback :save, :around, :around_it
+ set_callback :save, :after, :third
+
+
+ attr_reader :history, :saved
+ def initialize
+ @history = []
+ end
+
+ def around_it
+ @history << "around1"
+ yield
+ @history << "around2"
+ end
+
+ def first
+ @history << "first"
+ end
+
+ def second
+ @history << "second"
+ :halt
+ end
+
+ def third
+ @history << "third"
+ end
+
+ def save
+ run_callbacks :save do
+ @saved = true
+ end
+ end
+ end
+
+ class CallbackObject
+ def before(caller)
+ caller.record << "before"
+ end
+
+ def before_save(caller)
+ caller.record << "before save"
+ end
+
+ def around(caller)
+ caller.record << "around before"
+ yield
+ caller.record << "around after"
+ end
+ end
+
+ class UsingObjectBefore
+ include ActiveSupport::Callbacks
+
+ define_callbacks :save
+ set_callback :save, :before, CallbackObject.new
+
+ attr_accessor :record
+ def initialize
+ @record = []
+ end
+
+ def save
+ run_callbacks :save do
+ @record << "yielded"
+ end
+ end
end
-end
-class CallbackChainTest < Test::Unit::TestCase
- include ActiveSupport::Callbacks
+ class UsingObjectAround
+ include ActiveSupport::Callbacks
- def setup
- @chain = CallbackChain.build(:make, :bacon, :lettuce, :tomato)
+ define_callbacks :save
+ set_callback :save, :around, CallbackObject.new
+
+ attr_accessor :record
+ def initialize
+ @record = []
+ end
+
+ def save
+ run_callbacks :save do
+ @record << "yielded"
+ end
+ end
end
- def test_build
- assert_equal 3, @chain.size
- assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method)
+ class CustomScopeObject
+ include ActiveSupport::Callbacks
+
+ define_callbacks :save, :scope => [:kind, :name]
+ set_callback :save, :before, CallbackObject.new
+
+ attr_accessor :record
+ def initialize
+ @record = []
+ end
+
+ def save
+ run_callbacks :save do
+ @record << "yielded"
+ "CallbackResult"
+ end
+ end
end
- def test_find
- assert_equal :bacon, @chain.find(:bacon).method
+ class UsingObjectTest < Test::Unit::TestCase
+ def test_before_object
+ u = UsingObjectBefore.new
+ u.save
+ assert_equal ["before", "yielded"], u.record
+ end
+
+ def test_around_object
+ u = UsingObjectAround.new
+ u.save
+ assert_equal ["around before", "yielded", "around after"], u.record
+ end
+
+ def test_customized_object
+ u = CustomScopeObject.new
+ u.save
+ assert_equal ["before save", "yielded"], u.record
+ end
+
+ def test_block_result_is_returned
+ u = CustomScopeObject.new
+ assert_equal "CallbackResult", u.save
+ end
end
- def test_replace_or_append
- assert_equal [:bacon, :lettuce, :tomato], (@chain.replace_or_append!(Callback.new(:make, :bacon))).map(&:method)
- assert_equal [:bacon, :lettuce, :tomato, :turkey], (@chain.replace_or_append!(Callback.new(:make, :turkey))).map(&:method)
- assert_equal [:bacon, :lettuce, :tomato, :turkey, :mayo], (@chain.replace_or_append!(Callback.new(:make, :mayo))).map(&:method)
+ class CallbackTerminatorTest < Test::Unit::TestCase
+ def test_termination
+ terminator = CallbackTerminator.new
+ terminator.save
+ assert_equal ["first", "second", "third", "second", "first"], terminator.history
+ end
+
+ def test_block_never_called_if_terminated
+ obj = CallbackTerminator.new
+ obj.save
+ assert !obj.saved
+ end
end
- def test_delete
- assert_equal [:bacon, :lettuce, :tomato], @chain.map(&:method)
- @chain.delete(:bacon)
- assert_equal [:lettuce, :tomato], @chain.map(&:method)
+ class HyphenatedKeyTest < Test::Unit::TestCase
+ def test_save
+ obj = HyphenatedCallbacks.new
+ obj.save
+ assert_equal obj.stuff, "OMG"
+ end
end
end