aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/test
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2009-04-20 18:31:22 -0700
committerJeremy Kemper <jeremy@bitsweat.net>2009-04-20 18:31:40 -0700
commit685a53a360d0d8fc4a9f3b49f900621c940a71f2 (patch)
treefa6b38f75a873a21c3e380f1acbab3d019293363 /activesupport/test
parentdb05c73fb6e2294c576ef9889c70940891682c32 (diff)
parent164a94d0bc8c9124ab820506e5ad79496395c026 (diff)
downloadrails-685a53a360d0d8fc4a9f3b49f900621c940a71f2.tar.gz
rails-685a53a360d0d8fc4a9f3b49f900621c940a71f2.tar.bz2
rails-685a53a360d0d8fc4a9f3b49f900621c940a71f2.zip
Merge branch 'master' into cherry
Conflicts: activesupport/CHANGELOG activesupport/lib/active_support/core_ext/class/delegating_attributes.rb activesupport/lib/active_support/core_ext/hash/conversions.rb activesupport/lib/active_support/core_ext/module/attribute_accessors.rb activesupport/lib/active_support/core_ext/string/multibyte.rb activesupport/lib/active_support/core_ext/time/calculations.rb activesupport/lib/active_support/deprecation.rb
Diffstat (limited to 'activesupport/test')
-rw-r--r--activesupport/test/core_ext/duration_test.rb12
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb73
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb4
-rw-r--r--activesupport/test/memoizable_test.rb11
-rw-r--r--activesupport/test/new_callback_inheritance_test.rb115
-rw-r--r--activesupport/test/new_callbacks_test.rb384
7 files changed, 582 insertions, 19 deletions
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 0e23c5c2dd..d4a4627e3e 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -89,6 +89,18 @@ class DurationTest < ActiveSupport::TestCase
ensure
Time.zone_default = nil
end
+
+ def test_adding_hours_across_dst_boundary
+ with_env_tz 'CET' do
+ assert_equal Time.local(2009,3,29,0,0,0) + 24.hours, Time.local(2009,3,30,1,0,0)
+ end
+ end
+
+ def test_adding_day_across_dst_boundary
+ with_env_tz 'CET' do
+ assert_equal Time.local(2009,3,29,0,0,0) + 1.day, Time.local(2009,3,30,0,0,0)
+ end
+ end
protected
def with_env_tz(new_tz = 'US/Eastern')
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index c8331b9ffc..a357ba5852 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -134,10 +134,12 @@ class StringInflectionsTest < Test::Unit::TestCase
assert_equal "h", s.first
assert_equal "he", s.first(2)
+ assert_equal "", s.first(0)
assert_equal "o", s.last
assert_equal "llo", s.last(3)
assert_equal "hello", s.last(10)
+ assert_equal "", s.last(0)
assert_equal 'x', 'x'.first
assert_equal 'x', 'x'.first(4)
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index c0855520e8..8ee4904036 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -183,26 +183,46 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
def test_daylight_savings_time_crossings_backward_start
with_env_tz 'US/Eastern' do
# dt: US: 2005 April 3rd 4:18am
- assert_equal Time.local(2005,4,2,4,18,0), Time.local(2005,4,3,4,18,0).ago(86400), 'dt-1.day=>st'
- assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400), 'st-1.day=>st'
+ assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(24.hours), 'dt-24.hours=>st'
+ assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(86400), 'dt-86400=>st'
+ assert_equal Time.local(2005,4,2,3,18,0), Time.local(2005,4,3,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st'
+
+ assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(24.hours), 'st-24.hours=>st'
+ assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400), 'st-86400=>st'
+ assert_equal Time.local(2005,4,1,4,18,0), Time.local(2005,4,2,4,18,0).ago(86400.seconds), 'st-86400.seconds=>st'
end
with_env_tz 'NZ' do
# dt: New Zealand: 2006 October 1st 4:18am
- assert_equal Time.local(2006,9,30,4,18,0), Time.local(2006,10,1,4,18,0).ago(86400), 'dt-1.day=>st'
- assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-1.day=>st'
+ assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(24.hours), 'dt-24.hours=>st'
+ assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400), 'dt-86400=>st'
+ assert_equal Time.local(2006,9,30,3,18,0), Time.local(2006,10,1,4,18,0).ago(86400.seconds), 'dt-86400.seconds=>st'
+
+ assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(24.hours), 'st-24.hours=>st'
+ assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400), 'st-86400=>st'
+ assert_equal Time.local(2006,9,29,4,18,0), Time.local(2006,9,30,4,18,0).ago(86400.seconds), 'st-86400.seconds=>st'
end
end
def test_daylight_savings_time_crossings_backward_end
with_env_tz 'US/Eastern' do
# st: US: 2005 October 30th 4:03am
- assert_equal Time.local(2005,10,29,4,3), Time.local(2005,10,30,4,3,0).ago(86400), 'st-1.day=>dt'
- assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400), 'dt-1.day=>dt'
+ assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(24.hours), 'st-24.hours=>dt'
+ assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(86400), 'st-86400=>dt'
+ assert_equal Time.local(2005,10,29,5,3), Time.local(2005,10,30,4,3,0).ago(86400.seconds), 'st-86400.seconds=>dt'
+
+ assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(24.hours), 'dt-24.hours=>dt'
+ assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400), 'dt-86400=>dt'
+ assert_equal Time.local(2005,10,28,4,3), Time.local(2005,10,29,4,3,0).ago(86400.seconds), 'dt-86400.seconds=>dt'
end
with_env_tz 'NZ' do
# st: New Zealand: 2006 March 19th 4:03am
- assert_equal Time.local(2006,3,18,4,3), Time.local(2006,3,19,4,3,0).ago(86400), 'st-1.day=>dt'
- assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400), 'dt-1.day=>dt'
+ assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(24.hours), 'st-24.hours=>dt'
+ assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(86400), 'st-86400=>dt'
+ assert_equal Time.local(2006,3,18,5,3), Time.local(2006,3,19,4,3,0).ago(86400.seconds), 'st-86400.seconds=>dt'
+
+ assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(24.hours), 'dt-24.hours=>dt'
+ assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400), 'dt-86400=>dt'
+ assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(86400.seconds), 'dt-86400.seconds=>dt'
end
end
@@ -231,6 +251,7 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
assert_equal Time.local(2006,3,17,4,3), Time.local(2006,3,18,4,3,0).ago(1.day), 'dt-1.day=>dt'
end
end
+
def test_since
assert_equal Time.local(2005,2,22,10,10,11), Time.local(2005,2,22,10,10,10).since(1)
assert_equal Time.local(2005,2,22,11,10,10), Time.local(2005,2,22,10,10,10).since(3600)
@@ -243,13 +264,23 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
def test_daylight_savings_time_crossings_forward_start
with_env_tz 'US/Eastern' do
# st: US: 2005 April 2nd 7:27pm
- assert_equal Time.local(2005,4,3,19,27,0), Time.local(2005,4,2,19,27,0).since(86400), 'st+1.day=>dt'
- assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400), 'dt+1.day=>dt'
+ assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(24.hours), 'st+24.hours=>dt'
+ assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400), 'st+86400=>dt'
+ assert_equal Time.local(2005,4,3,20,27,0), Time.local(2005,4,2,19,27,0).since(86400.seconds), 'st+86400.seconds=>dt'
+
+ assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(24.hours), 'dt+24.hours=>dt'
+ assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400), 'dt+86400=>dt'
+ assert_equal Time.local(2005,4,4,19,27,0), Time.local(2005,4,3,19,27,0).since(86400.seconds), 'dt+86400.seconds=>dt'
end
with_env_tz 'NZ' do
# st: New Zealand: 2006 September 30th 7:27pm
- assert_equal Time.local(2006,10,1,19,27,0), Time.local(2006,9,30,19,27,0).since(86400), 'st+1.day=>dt'
- assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400), 'dt+1.day=>dt'
+ assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(24.hours), 'st+24.hours=>dt'
+ assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(86400), 'st+86400=>dt'
+ assert_equal Time.local(2006,10,1,20,27,0), Time.local(2006,9,30,19,27,0).since(86400.seconds), 'st+86400.seconds=>dt'
+
+ assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(24.hours), 'dt+24.hours=>dt'
+ assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400), 'dt+86400=>dt'
+ assert_equal Time.local(2006,10,2,19,27,0), Time.local(2006,10,1,19,27,0).since(86400.seconds), 'dt+86400.seconds=>dt'
end
end
@@ -295,13 +326,23 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
def test_daylight_savings_time_crossings_forward_end
with_env_tz 'US/Eastern' do
# dt: US: 2005 October 30th 12:45am
- assert_equal Time.local(2005,10,31,0,45,0), Time.local(2005,10,30,0,45,0).since(86400), 'dt+1.day=>st'
- assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400), 'st+1.day=>st'
+ assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(24.hours), 'dt+24.hours=>st'
+ assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(86400), 'dt+86400=>st'
+ assert_equal Time.local(2005,10,30,23,45,0), Time.local(2005,10,30,0,45,0).since(86400.seconds), 'dt+86400.seconds=>st'
+
+ assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(24.hours), 'st+24.hours=>st'
+ assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400), 'st+86400=>st'
+ assert_equal Time.local(2005,11, 1,0,45,0), Time.local(2005,10,31,0,45,0).since(86400.seconds), 'st+86400.seconds=>st'
end
with_env_tz 'NZ' do
# dt: New Zealand: 2006 March 19th 1:45am
- assert_equal Time.local(2006,3,20,1,45,0), Time.local(2006,3,19,1,45,0).since(86400), 'dt+1.day=>st'
- assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400), 'st+1.day=>st'
+ assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(24.hours), 'dt+24.hours=>st'
+ assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(86400), 'dt+86400=>st'
+ assert_equal Time.local(2006,3,20,0,45,0), Time.local(2006,3,19,1,45,0).since(86400.seconds), 'dt+86400.seconds=>st'
+
+ assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(24.hours), 'st+24.hours=>st'
+ assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400), 'st+86400=>st'
+ assert_equal Time.local(2006,3,21,1,45,0), Time.local(2006,3,20,1,45,0).since(86400.seconds), 'st+86400.seconds=>st'
end
end
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index bcb0180db6..3dec4c95f4 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -318,6 +318,10 @@ class TimeWithZoneTest < Test::Unit::TestCase
assert @twz.kind_of?(Time)
assert @twz.is_a?(ActiveSupport::TimeWithZone)
end
+
+ def test_class_name
+ assert_equal 'Time', ActiveSupport::TimeWithZone.name
+ end
def test_method_missing_with_time_return_value
assert_instance_of ActiveSupport::TimeWithZone, @twz.months_since(1)
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index 39420c5a3a..214e243aa5 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -1,6 +1,6 @@
require 'abstract_unit'
-class MemoizableTest < Test::Unit::TestCase
+class MemoizableTest < ActiveSupport::TestCase
class Person
extend ActiveSupport::Memoizable
@@ -125,8 +125,13 @@ class MemoizableTest < Test::Unit::TestCase
end
def test_memorized_results_are_immutable
- assert_equal "Josh", @person.name
- assert_raise(ActiveSupport::FrozenObjectError) { @person.name.gsub!("Josh", "Gosh") }
+ # This is purely a performance enhancement that we can revisit once the rest of
+ # the code is in place. Ideally, we'd be able to do memoization in a freeze-friendly
+ # way without amc hacks
+ pending do
+ assert_equal "Josh", @person.name
+ assert_raise(ActiveSupport::FrozenObjectError) { @person.name.gsub!("Josh", "Gosh") }
+ end
end
def test_reloadable
diff --git a/activesupport/test/new_callback_inheritance_test.rb b/activesupport/test/new_callback_inheritance_test.rb
new file mode 100644
index 0000000000..95020389b0
--- /dev/null
+++ b/activesupport/test/new_callback_inheritance_test.rb
@@ -0,0 +1,115 @@
+require 'test/unit'
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'active_support'
+
+class GrandParent
+ include ActiveSupport::NewCallbacks
+
+ attr_reader :log, :action_name
+ def initialize(action_name)
+ @action_name, @log = action_name, []
+ end
+
+ define_callbacks :dispatch
+ dispatch_callback :before, :before1, :before2, :per_key => {:if => proc {|c| c.action_name == "index" || c.action_name == "update" }}
+ dispatch_callback :after, :after1, :after2, :per_key => {:if => proc {|c| c.action_name == "update" || c.action_name == "delete" }}
+
+ def before1
+ @log << "before1"
+ end
+
+ def before2
+ @log << "before2"
+ end
+
+ def after1
+ @log << "after1"
+ end
+
+ def after2
+ @log << "after2"
+ end
+
+ def dispatch
+ _run_dispatch_callbacks(action_name) do
+ @log << action_name
+ end
+ self
+ end
+end
+
+class Parent < GrandParent
+ skip_dispatch_callback :before, :before2, :per_key => {:unless => proc {|c| c.action_name == "update" }}
+ skip_dispatch_callback :after, :after2, :per_key => {:unless => proc {|c| c.action_name == "delete" }}
+end
+
+class Child < GrandParent
+ skip_dispatch_callback :before, :before2, :per_key => {:unless => proc {|c| c.action_name == "update" }}, :if => :state_open?
+
+ def state_open?
+ @state == :open
+ end
+
+ def initialize(action_name, state)
+ super(action_name)
+ @state = state
+ end
+end
+
+
+class BasicCallbacksTest < Test::Unit::TestCase
+ def setup
+ @index = GrandParent.new("index").dispatch
+ @update = GrandParent.new("update").dispatch
+ @delete = GrandParent.new("delete").dispatch
+ @unknown = GrandParent.new("unknown").dispatch
+ end
+
+ def test_basic_per_key1
+ assert_equal %w(before1 before2 index), @index.log
+ end
+
+ def test_basic_per_key2
+ assert_equal %w(before1 before2 update after2 after1), @update.log
+ end
+
+ def test_basic_per_key3
+ assert_equal %w(delete after2 after1), @delete.log
+ end
+end
+
+class InheritedCallbacksTest < Test::Unit::TestCase
+ def setup
+ @index = Parent.new("index").dispatch
+ @update = Parent.new("update").dispatch
+ @delete = Parent.new("delete").dispatch
+ @unknown = Parent.new("unknown").dispatch
+ end
+
+ def test_inherited_excluded
+ assert_equal %w(before1 index), @index.log
+ end
+
+ def test_inherited_not_excluded
+ assert_equal %w(before1 before2 update after1), @update.log
+ end
+
+ def test_partially_excluded
+ assert_equal %w(delete after2 after1), @delete.log
+ end
+end
+
+class InheritedCallbacksTest2 < Test::Unit::TestCase
+ def setup
+ @update1 = Child.new("update", :open).dispatch
+ @update2 = Child.new("update", :closed).dispatch
+ end
+
+ def test_crazy_mix_on
+ assert_equal %w(before1 update after2 after1), @update1.log
+ end
+
+ def test_crazy_mix_off
+ assert_equal %w(before1 before2 update after2 after1), @update2.log
+ end
+end \ No newline at end of file
diff --git a/activesupport/test/new_callbacks_test.rb b/activesupport/test/new_callbacks_test.rb
new file mode 100644
index 0000000000..5cde078b65
--- /dev/null
+++ b/activesupport/test/new_callbacks_test.rb
@@ -0,0 +1,384 @@
+# require 'abstract_unit'
+require 'test/unit'
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'active_support'
+
+module NewCallbacksTest
+ class Record
+ include ActiveSupport::NewCallbacks
+
+ define_callbacks :save
+
+ def self.before_save(*filters, &blk)
+ save_callback(:before, *filters, &blk)
+ end
+
+ def self.after_save(*filters, &blk)
+ save_callback(:after, *filters, &blk)
+ end
+
+ class << self
+ def callback_symbol(callback_method)
+ returning(:"#{callback_method}_method") do |method_name|
+ define_method(method_name) do
+ history << [callback_method, :symbol]
+ end
+ end
+ 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, :object]
+ end
+ klass.new
+ end
+ end
+
+ 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))
+ send(callback_method) { |model| model.history << [callback_method_sym, :block] }
+ end
+
+ def save
+ _run_save_callbacks {}
+ end
+ end
+
+ class PersonSkipper < Person
+ skip_save_callback :before, :before_save_method, :if => :yes
+ skip_save_callback :after, :before_save_method, :unless => :yes
+ skip_save_callback :after, :before_save_method, :if => :no
+ skip_save_callback :before, :before_save_method, :unless => :no
+ def yes; true; end
+ def no; false; end
+ end
+
+ class ParentController
+ include ActiveSupport::NewCallbacks
+
+ define_callbacks :dispatch
+
+ dispatch_callback :before, :log, :per_key => {:unless => proc {|c| c.action_name == :index || c.action_name == :show }}
+ dispatch_callback :after, :log2
+
+ 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_dispatch_callbacks(action_name) {
+ @logger << "Done"
+ }
+ self
+ end
+ end
+
+ class Child < ParentController
+ skip_dispatch_callback :before, :log, :per_key => {:if => proc {|c| c.action_name == :update} }
+ skip_dispatch_callback :after, :log2
+ end
+
+ 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_save_callbacks(:action) {}
+ end
+ end
+
+ 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
+
+ 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_save_callbacks {}
+ end
+ end
+
+ class MySuper
+ include ActiveSupport::NewCallbacks
+ define_callbacks :save
+ end
+
+ class AroundPerson < MySuper
+ attr_reader :history
+
+ save_callback :before, :nope, :if => :no
+ save_callback :before, :nope, :unless => :yes
+ save_callback :after, :tweedle
+ save_callback :before, "tweedle_dee"
+ save_callback :before, proc {|m| m.history << "yup" }
+ save_callback :before, :nope, :if => proc { false }
+ save_callback :before, :nope, :unless => proc { true }
+ save_callback :before, :yup, :if => proc { true }
+ save_callback :before, :yup, :unless => proc { false }
+ save_callback :around, :tweedle_dum
+ save_callback :around, :w0tyes, :if => :yes
+ save_callback :around, :w0tno, :if => :no
+ save_callback :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 save
+ _run_save_callbacks do
+ @history << "running"
+ 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 CallbackTerminator
+ include ActiveSupport::NewCallbacks
+
+ define_callbacks :save, "result == :halt"
+
+ save_callback :before, :first
+ save_callback :before, :second
+ save_callback :around, :around_it
+ save_callback :before, :third
+ save_callback :after, :first
+ save_callback :around, :around_it
+ save_callback :after, :second
+ save_callback :around, :around_it
+ save_callback :after, :third
+
+
+ attr_reader :history
+ 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_save_callbacks
+ end
+ end
+
+ class CallbackTerminatorTest < Test::Unit::TestCase
+ def test_termination
+ terminator = CallbackTerminator.new
+ terminator.save
+ assert_equal ["first", "second", "third", "second", "first"], terminator.history
+ end
+ end
+end \ No newline at end of file