aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2009-12-31 01:15:30 -0500
committerDavid Heinemeier Hansson <david@loudthinking.com>2009-12-31 01:15:30 -0500
commit96c27e4003b803b9ac1a3581dfe1c181ba79556a (patch)
tree24a6c8573dfe3aa01abd4464eafbeb86e96cd250 /activesupport/lib/active_support
parent5d8342cc325bc9f46bfe61bf3534248b6ad3216f (diff)
parentc4c2502df8b0b7b5fa28d796bdb1d4bd02af4b3d (diff)
downloadrails-96c27e4003b803b9ac1a3581dfe1c181ba79556a.tar.gz
rails-96c27e4003b803b9ac1a3581dfe1c181ba79556a.tar.bz2
rails-96c27e4003b803b9ac1a3581dfe1c181ba79556a.zip
Merge branch 'master' of github.com:rails/rails
Diffstat (limited to 'activesupport/lib/active_support')
-rw-r--r--activesupport/lib/active_support/callbacks.rb2
-rw-r--r--activesupport/lib/active_support/deprecated_callbacks.rb284
-rw-r--r--activesupport/lib/active_support/testing/isolation.rb64
-rw-r--r--activesupport/lib/active_support/testing/setup_and_teardown.rb73
4 files changed, 93 insertions, 330 deletions
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index 97e2a478b5..05bc453dbf 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -90,7 +90,7 @@ module ActiveSupport
class Callback
@@_callback_sequence = 0
- attr_accessor :chain, :filter, :kind, :options, :per_key, :klass
+ attr_accessor :chain, :filter, :kind, :options, :per_key, :klass, :raw_filter
def initialize(chain, filter, kind, options, klass)
@chain, @kind, @klass = chain, kind, klass
diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb
deleted file mode 100644
index f56fef0b6d..0000000000
--- a/activesupport/lib/active_support/deprecated_callbacks.rb
+++ /dev/null
@@ -1,284 +0,0 @@
-require 'active_support/core_ext/array/extract_options'
-require 'active_support/core_ext/array/wrap'
-
-module ActiveSupport
- # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
- # before or after an alteration of the object state.
- #
- # Mixing in this module allows you to define callbacks in your class.
- #
- # Example:
- # class Storage
- # include ActiveSupport::DeprecatedCallbacks
- #
- # define_callbacks :before_save, :after_save
- # end
- #
- # class ConfigStorage < Storage
- # before_save :saving_message
- # def saving_message
- # puts "saving..."
- # end
- #
- # after_save do |object|
- # puts "saved"
- # end
- #
- # def save
- # run_callbacks(:before_save)
- # puts "- save"
- # run_callbacks(:after_save)
- # end
- # end
- #
- # config = ConfigStorage.new
- # config.save
- #
- # Output:
- # saving...
- # - save
- # saved
- #
- # Callbacks from parent classes are inherited.
- #
- # Example:
- # class Storage
- # include ActiveSupport::DeprecatedCallbacks
- #
- # define_callbacks :before_save, :after_save
- #
- # before_save :prepare
- # def prepare
- # puts "preparing save"
- # end
- # end
- #
- # class ConfigStorage < Storage
- # before_save :saving_message
- # def saving_message
- # puts "saving..."
- # end
- #
- # after_save do |object|
- # puts "saved"
- # end
- #
- # def save
- # run_callbacks(:before_save)
- # puts "- save"
- # run_callbacks(:after_save)
- # end
- # end
- #
- # config = ConfigStorage.new
- # config.save
- #
- # Output:
- # preparing save
- # saving...
- # - save
- # saved
- module DeprecatedCallbacks
- class CallbackChain < Array
- def self.build(kind, *methods, &block)
- methods, options = extract_options(*methods, &block)
- methods.map! { |method| Callback.new(kind, method, options) }
- new(methods)
- end
-
- def run(object, options = {}, &terminator)
- enumerator = options[:enumerator] || :each
-
- unless block_given?
- send(enumerator) { |callback| callback.call(object) }
- else
- send(enumerator) do |callback|
- result = callback.call(object)
- break result if terminator.call(result, object)
- end
- end
- end
-
- # TODO: Decompose into more Array like behavior
- def replace_or_append!(chain)
- if index = index(chain)
- self[index] = chain
- else
- self << chain
- end
- self
- end
-
- def find(callback, &block)
- select { |c| c == callback && (!block_given? || yield(c)) }.first
- end
-
- def delete(callback)
- super(callback.is_a?(Callback) ? callback : find(callback))
- end
-
- private
- def self.extract_options(*methods, &block)
- methods.flatten!
- options = methods.extract_options!
- methods << block if block_given?
- return methods, options
- end
-
- def extract_options(*methods, &block)
- self.class.extract_options(*methods, &block)
- end
- end
-
- class Callback
- attr_reader :kind, :method, :identifier, :options
-
- def initialize(kind, method, options = {})
- @kind = kind
- @method = method
- @identifier = options[:identifier]
- @options = options
- end
-
- def ==(other)
- case other
- when Callback
- (self.identifier && self.identifier == other.identifier) || self.method == other.method
- else
- (self.identifier && self.identifier == other) || self.method == other
- end
- end
-
- def eql?(other)
- self == other
- end
-
- def dup
- self.class.new(@kind, @method, @options.dup)
- end
-
- def hash
- if @identifier
- @identifier.hash
- else
- @method.hash
- end
- end
-
- def call(*args, &block)
- evaluate_method(method, *args, &block) if should_run_callback?(*args)
- rescue LocalJumpError
- raise ArgumentError,
- "Cannot yield from a Proc type filter. The Proc must take two " +
- "arguments and execute #call on the second argument."
- end
-
- private
- def evaluate_method(method, *args, &block)
- case method
- when Symbol
- object = args.shift
- object.send(method, *args, &block)
- when String
- eval(method, args.first.instance_eval { binding })
- when Proc, Method
- method.call(*args, &block)
- else
- if method.respond_to?(kind)
- method.send(kind, *args, &block)
- else
- raise ArgumentError,
- "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
- "a block to be invoked, or an object responding to the callback method."
- end
- end
- end
-
- def should_run_callback?(*args)
- Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } &&
- !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) }
- end
- end
-
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def define_callbacks(*callbacks)
- ActiveSupport::Deprecation.warn('ActiveSupport::DeprecatedCallbacks has been deprecated in favor of ActiveSupport::Callbacks', caller)
-
- callbacks.each do |callback|
- class_eval <<-"end_eval", __FILE__, __LINE__ + 1
- def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block)
- callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block)
- @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
- @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks
- end # end
- #
- def self.#{callback}_callback_chain # def self.before_save_callback_chain
- @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
- #
- if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain)
- CallbackChain.new( # CallbackChain.new(
- superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain +
- @#{callback}_callbacks # @before_save_callbacks
- ) # )
- else # else
- @#{callback}_callbacks # @before_save_callbacks
- end # end
- end # end
- end_eval
- end
- end
- end
-
- # Runs all the callbacks defined for the given options.
- #
- # If a block is given it will be called after each callback receiving as arguments:
- #
- # * the result from the callback
- # * the object which has the callback
- #
- # If the result from the block evaluates to +true+, the callback chain is stopped.
- #
- # Example:
- # class Storage
- # include ActiveSupport::DeprecatedCallbacks
- #
- # define_callbacks :before_save, :after_save
- # end
- #
- # class ConfigStorage < Storage
- # before_save :pass
- # before_save :pass
- # before_save :stop
- # before_save :pass
- #
- # def pass
- # puts "pass"
- # end
- #
- # def stop
- # puts "stop"
- # return false
- # end
- #
- # def save
- # result = run_callbacks(:before_save) { |result, object| result == false }
- # puts "- save" if result
- # end
- # end
- #
- # config = ConfigStorage.new
- # config.save
- #
- # Output:
- # pass
- # pass
- # stop
- def run_callbacks(kind, options = {}, &block)
- self.class.send("#{kind}_callback_chain").run(self, options, &block)
- end
- end
-end
diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb
index 81f7e3c9df..453f4fcc0f 100644
--- a/activesupport/lib/active_support/testing/isolation.rb
+++ b/activesupport/lib/active_support/testing/isolation.rb
@@ -36,28 +36,56 @@ module ActiveSupport
!ENV["NO_FORK"] && RUBY_PLATFORM !~ /mswin|mingw|java/
end
- def run(result)
- unless defined?(@@ran_class_setup)
- self.class.setup if self.class.respond_to?(:setup)
- @@ran_class_setup = true
+ def self.included(base)
+ if defined?(::MiniTest) && base < ::MiniTest::Unit::TestCase
+ base.send :include, MiniTest
+ elsif defined?(Test::Unit)
+ base.send :include, TestUnit
end
+ end
+
+ module TestUnit
+ def run(result)
+ unless defined?(@@ran_class_setup)
+ self.class.setup if self.class.respond_to?(:setup)
+ @@ran_class_setup = true
+ end
- yield(Test::Unit::TestCase::STARTED, name)
+ yield(Test::Unit::TestCase::STARTED, name)
- @_result = result
+ @_result = result
- serialized = run_in_isolation do |proxy|
- begin
- super(proxy) { }
- rescue Exception => e
- proxy.add_error(Test::Unit::Error.new(name, e))
+ serialized = run_in_isolation do |proxy|
+ begin
+ super(proxy) { }
+ rescue Exception => e
+ proxy.add_error(Test::Unit::Error.new(name, e))
+ end
end
+
+ retval, proxy = Marshal.load(serialized)
+ proxy.__replay__(@_result)
+
+ yield(Test::Unit::TestCase::FINISHED, name)
+ retval
end
+ end
- proxy = Marshal.load(serialized)
- proxy.__replay__(@_result)
+ module MiniTest
+ def run(runner)
+ unless defined?(@@ran_class_setup)
+ self.class.setup if self.class.respond_to?(:setup)
+ @@ran_class_setup = true
+ end
- yield(Test::Unit::TestCase::FINISHED, name)
+ serialized = run_in_isolation do |runner|
+ super(runner)
+ end
+
+ retval, proxy = Marshal.load(serialized)
+ proxy.__replay__(runner)
+ retval
+ end
end
module Forking
@@ -67,8 +95,8 @@ module ActiveSupport
pid = fork do
read.close
proxy = ProxyTestResult.new
- yield proxy
- write.puts [Marshal.dump(proxy)].pack("m")
+ retval = yield proxy
+ write.puts [Marshal.dump([retval, proxy])].pack("m")
exit!
end
@@ -87,9 +115,9 @@ module ActiveSupport
if ENV["ISOLATION_TEST"]
proxy = ProxyTestResult.new
- yield proxy
+ retval = yield proxy
File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
- file.puts [Marshal.dump(proxy)].pack("m")
+ file.puts [Marshal.dump([retval, proxy])].pack("m")
end
exit!
else
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
index 0e998d2dbe..6ce9495cee 100644
--- a/activesupport/lib/active_support/testing/setup_and_teardown.rb
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -1,16 +1,26 @@
module ActiveSupport
module Testing
module SetupAndTeardown
- def self.included(base)
- base.class_eval do
- include ActiveSupport::DeprecatedCallbacks
- define_callbacks :setup, :teardown
+ extend ActiveSupport::Concern
- if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
- include ForMiniTest
- else
- include ForClassicTestUnit
- end
+ included do
+ include ActiveSupport::Callbacks
+ define_callbacks :setup, :teardown
+
+ if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
+ include ForMiniTest
+ else
+ include ForClassicTestUnit
+ end
+ end
+
+ module ClassMethods
+ def setup(*args, &block)
+ set_callback(:setup, :before, *args, &block)
+ end
+
+ def teardown(*args, &block)
+ set_callback(:teardown, :after, *args, &block)
end
end
@@ -18,13 +28,14 @@ module ActiveSupport
def run(runner)
result = '.'
begin
- run_callbacks :setup
- result = super
+ _run_setup_callbacks do
+ result = super
+ end
rescue Exception => e
result = runner.puke(self.class, method_name, e)
ensure
begin
- run_callbacks :teardown, :enumerator => :reverse_each
+ _run_teardown_callbacks
rescue Exception => e
result = runner.puke(self.class, method_name, e)
end
@@ -42,23 +53,17 @@ module ActiveSupport
def run(result)
return if @method_name.to_s == "default_test"
- if using_mocha = respond_to?(:mocha_verify)
- assertion_counter_klass = if defined?(Mocha::TestCaseAdapter::AssertionCounter)
- Mocha::TestCaseAdapter::AssertionCounter
- else
- Mocha::Integration::TestUnit::AssertionCounter
- end
- assertion_counter = assertion_counter_klass.new(result)
- end
-
+ mocha_counter = retrieve_mocha_counter(result)
yield(Test::Unit::TestCase::STARTED, name)
@_result = result
+
begin
begin
- run_callbacks :setup
- setup
- __send__(@method_name)
- mocha_verify(assertion_counter) if using_mocha
+ _run_setup_callbacks do
+ setup
+ __send__(@method_name)
+ mocha_verify(mocha_counter) if mocha_counter
+ end
rescue Mocha::ExpectationError => e
add_failure(e.message, e.backtrace)
rescue Test::Unit::AssertionFailedError => e
@@ -69,7 +74,7 @@ module ActiveSupport
ensure
begin
teardown
- run_callbacks :teardown, :enumerator => :reverse_each
+ _run_teardown_callbacks
rescue Test::Unit::AssertionFailedError => e
add_failure(e.message, e.backtrace)
rescue Exception => e
@@ -78,12 +83,26 @@ module ActiveSupport
end
end
ensure
- mocha_teardown if using_mocha
+ mocha_teardown if mocha_counter
end
+
result.add_run
yield(Test::Unit::TestCase::FINISHED, name)
end
+
+ protected
+
+ def retrieve_mocha_counter(result) #:nodoc:
+ if using_mocha = respond_to?(:mocha_verify)
+ if defined?(Mocha::TestCaseAdapter::AssertionCounter)
+ Mocha::TestCaseAdapter::AssertionCounter.new(result)
+ else
+ Mocha::Integration::TestUnit::AssertionCounter.new(result)
+ end
+ end
+ end
end
+
end
end
end