Permalink
Browse files

Merge commit 'josevalim/callbacks'

  • Loading branch information...
2 parents bb153f4 + 97a64b6 commit 17787fbfdbb1aa8fa8838e447e9acc7068eab130 @jeremy jeremy committed Dec 30, 2009
View
9 activerecord/lib/active_record/associations/association_collection.rb
@@ -485,7 +485,14 @@ def remove_records(*records)
def callback(method, record)
callbacks_for(method).each do |callback|
- ActiveSupport::DeprecatedCallbacks::Callback.new(method, callback, record).call(@owner, record)
+ case callback
+ when Symbol
+ @owner.send(callback, record)
+ when Proc
+ callback.call(@owner, record)
+ else
+ callback.send(method, @owner, record)
+ end
end
end
View
2 activerecord/lib/active_record/callbacks.rb
@@ -274,7 +274,7 @@ def destroy_with_callbacks #:nodoc:
def deprecated_callback_method(symbol) #:nodoc:
if respond_to?(symbol)
- ActiveSupport::Deprecation.warn("Base##{symbol} has been deprecated, please use Base.#{symbol} :method instead")
+ ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base##{symbol} :method_name instead")
send(symbol)
end
end
View
2 activerecord/lib/active_record/validations.rb
@@ -17,8 +17,6 @@ def initialize(record)
module Validations
extend ActiveSupport::Concern
-
- include ActiveSupport::DeprecatedCallbacks
include ActiveModel::Validations
included do
View
1 activesupport/lib/active_support.rb
@@ -50,7 +50,6 @@ module ActiveSupport
autoload :Callbacks
autoload :Concern
autoload :Configurable
- autoload :DeprecatedCallbacks
autoload :Deprecation
autoload :Gzip
autoload :Inflector
View
2 activesupport/lib/active_support/callbacks.rb
@@ -90,7 +90,7 @@ def run_callbacks(kind, *args, &block)
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
View
284 activesupport/lib/active_support/deprecated_callbacks.rb
@@ -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
View
73 activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -1,30 +1,41 @@
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
module ForMiniTest
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 ForClassicTestUnit
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 @@ def run(result)
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 @@ def run(result)
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
View
9 activesupport/test/test_test.rb
@@ -102,9 +102,9 @@ class SetupAndTeardownTest < ActiveSupport::TestCase
teardown :foo, :sentinel, :foo
def test_inherited_setup_callbacks
- assert_equal [:reset_callback_record, :foo], self.class.setup_callback_chain.map(&:method)
+ assert_equal [:reset_callback_record, :foo], self.class._setup_callbacks.map(&:raw_filter)
assert_equal [:foo], @called_back
- assert_equal [:foo, :sentinel, :foo], self.class.teardown_callback_chain.map(&:method)
+ assert_equal [:foo, :sentinel, :foo], self.class._teardown_callbacks.map(&:raw_filter)
end
def setup
@@ -114,6 +114,7 @@ def teardown
end
protected
+
def reset_callback_record
@called_back = []
end
@@ -133,9 +134,9 @@ class SubclassSetupAndTeardownTest < SetupAndTeardownTest
teardown :bar
def test_inherited_setup_callbacks
- assert_equal [:reset_callback_record, :foo, :bar], self.class.setup_callback_chain.map(&:method)
+ assert_equal [:reset_callback_record, :foo, :bar], self.class._setup_callbacks.map(&:raw_filter)
assert_equal [:foo, :bar], @called_back
- assert_equal [:foo, :sentinel, :foo, :bar], self.class.teardown_callback_chain.map(&:method)
+ assert_equal [:foo, :sentinel, :foo, :bar], self.class._teardown_callbacks.map(&:raw_filter)
end
protected

0 comments on commit 17787fb

Please sign in to comment.