From 4f37b97033f596ec2c95eb53e9964e051c224981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 8 Sep 2009 10:10:14 -0500 Subject: Changed ActiveRecord to use new callbacks and speed up observers by only notifying events that are actually being consumed. Signed-off-by: Joshua Peek --- .../associations/has_many_associations_test.rb | 2 +- activerecord/test/cases/callbacks_test.rb | 118 ++++++++++----------- activerecord/test/cases/helper.rb | 2 - activerecord/test/cases/lifecycle_test.rb | 19 ++-- activerecord/test/cases/repair_helper.rb | 46 -------- activerecord/test/cases/transactions_test.rb | 10 +- .../i18n_generate_message_validation_test.rb | 12 +-- .../test/cases/validations/i18n_validation_test.rb | 24 +---- activerecord/test/cases/validations_test.rb | 9 +- 9 files changed, 78 insertions(+), 164 deletions(-) delete mode 100644 activerecord/test/cases/repair_helper.rb (limited to 'activerecord/test/cases') diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index f7178f2c5e..b193f8d8ba 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -813,7 +813,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase firm = companies(:first_firm) clients = firm.clients assert_equal 2, clients.length - clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end } + clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end } firm.destroy rescue "do nothing" diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 95fddaeef6..092522b441 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -13,40 +13,34 @@ class CallbackDeveloper < ActiveRecord::Base end def define_callback_method(callback_method) - define_method("#{callback_method}_method") do |model| - model.history << [callback_method, :method] + define_method(callback_method) do + self.history << [callback_method, :method] end end - def callback_object(callback_method) + def callback_object(callback_symbol) klass = Class.new + callback_method = callback_symbol.to_s.split('_').first.to_sym klass.send(:define_method, callback_method) do |model| - model.history << [callback_method, :object] + model.history << [callback_symbol, :object] end klass.new end end - ActiveRecord::Callbacks::CALLBACKS.each do |callback_method| - callback_method_sym = callback_method.to_sym - define_callback_method(callback_method_sym) - send(callback_method, 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] } + ActiveSupport::Deprecation.silence do + ActiveRecord::Callbacks::CALLBACKS.each do |callback_method| + define_callback_method(callback_method) + send(callback_method, callback_string(callback_method)) + send(callback_method, callback_proc(callback_method)) + send(callback_method, callback_object(callback_method)) + send(callback_method) { |model| model.history << [callback_method, :block] } + end end def history @history ||= [] end - - # after_initialize and after_find are invoked only if instance methods have been defined. - def after_initialize - end - - def after_find - end end class ParentDeveloper < ActiveRecord::Base @@ -108,12 +102,12 @@ class ImmutableMethodDeveloper < ActiveRecord::Base @cancelled == true end - def before_save + before_save do @cancelled = true false end - def before_destroy + before_destroy do @cancelled = true false end @@ -125,15 +119,15 @@ class CallbackCancellationDeveloper < ActiveRecord::Base attr_reader :after_save_called, :after_create_called, :after_update_called, :after_destroy_called attr_accessor :cancel_before_save, :cancel_before_create, :cancel_before_update, :cancel_before_destroy - def before_save; !@cancel_before_save; end - def before_create; !@cancel_before_create; end - def before_update; !@cancel_before_update; end - def before_destroy; !@cancel_before_destroy; end + before_save { !@cancel_before_save } + before_create { !@cancel_before_create } + before_update { !@cancel_before_update } + before_destroy { !@cancel_before_destroy } - def after_save; @after_save_called = true; end - def after_update; @after_update_called = true; end - def after_create; @after_create_called = true; end - def after_destroy; @after_destroy_called = true; end + after_save { @after_save_called = true } + after_update { @after_update_called = true } + after_create { @after_create_called = true } + after_destroy { @after_destroy_called = true } end class CallbacksTest < ActiveRecord::TestCase @@ -142,6 +136,7 @@ class CallbacksTest < ActiveRecord::TestCase def test_initialize david = CallbackDeveloper.new assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -152,10 +147,12 @@ class CallbacksTest < ActiveRecord::TestCase def test_find david = CallbackDeveloper.find(1) assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -167,26 +164,21 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.new david.valid? assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_create, :string ], - [ :before_validation_on_create, :proc ], - [ :before_validation_on_create, :object ], - [ :before_validation_on_create, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_create, :string ], - [ :after_validation_on_create, :proc ], - [ :after_validation_on_create, :object ], - [ :after_validation_on_create, :block ] ], david.history end @@ -194,68 +186,63 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.valid? assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_update, :string ], - [ :before_validation_on_update, :proc ], - [ :before_validation_on_update, :object ], - [ :before_validation_on_update, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_update, :string ], - [ :after_validation_on_update, :proc ], - [ :after_validation_on_update, :object ], - [ :after_validation_on_update, :block ] ], david.history end def test_create david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000) assert_equal [ + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_create, :string ], - [ :before_validation_on_create, :proc ], - [ :before_validation_on_create, :object ], - [ :before_validation_on_create, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_create, :string ], - [ :after_validation_on_create, :proc ], - [ :after_validation_on_create, :object ], - [ :after_validation_on_create, :block ], + [ :before_save, :method ], [ :before_save, :string ], [ :before_save, :proc ], [ :before_save, :object ], [ :before_save, :block ], + [ :before_create, :method ], [ :before_create, :string ], [ :before_create, :proc ], [ :before_create, :object ], [ :before_create, :block ], + [ :after_create, :method ], [ :after_create, :string ], [ :after_create, :proc ], [ :after_create, :object ], [ :after_create, :block ], + [ :after_save, :method ], [ :after_save, :string ], [ :after_save, :proc ], [ :after_save, :object ], @@ -267,42 +254,42 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.save assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], [ :before_validation, :block ], - [ :before_validation_on_update, :string ], - [ :before_validation_on_update, :proc ], - [ :before_validation_on_update, :object ], - [ :before_validation_on_update, :block ], + [ :after_validation, :method ], [ :after_validation, :string ], [ :after_validation, :proc ], [ :after_validation, :object ], [ :after_validation, :block ], - [ :after_validation_on_update, :string ], - [ :after_validation_on_update, :proc ], - [ :after_validation_on_update, :object ], - [ :after_validation_on_update, :block ], + [ :before_save, :method ], [ :before_save, :string ], [ :before_save, :proc ], [ :before_save, :object ], [ :before_save, :block ], + [ :before_update, :method ], [ :before_update, :string ], [ :before_update, :proc ], [ :before_update, :object ], [ :before_update, :block ], + [ :after_update, :method ], [ :after_update, :string ], [ :after_update, :proc ], [ :after_update, :object ], [ :after_update, :block ], + [ :after_save, :method ], [ :after_save, :string ], [ :after_save, :proc ], [ :after_save, :object ], @@ -314,18 +301,22 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) david.destroy assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_destroy, :method ], [ :before_destroy, :string ], [ :before_destroy, :proc ], [ :before_destroy, :object ], [ :before_destroy, :block ], + [ :after_destroy, :method ], [ :after_destroy, :string ], [ :after_destroy, :proc ], [ :after_destroy, :object ], @@ -337,10 +328,12 @@ class CallbacksTest < ActiveRecord::TestCase david = CallbackDeveloper.find(1) CallbackDeveloper.delete(david.id) assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], @@ -407,14 +400,17 @@ class CallbacksTest < ActiveRecord::TestCase CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] } david.save assert_equal [ + [ :after_find, :method ], [ :after_find, :string ], [ :after_find, :proc ], [ :after_find, :object ], [ :after_find, :block ], + [ :after_initialize, :method ], [ :after_initialize, :string ], [ :after_initialize, :proc ], [ :after_initialize, :object ], [ :after_initialize, :block ], + [ :before_validation, :method ], [ :before_validation, :string ], [ :before_validation, :proc ], [ :before_validation, :object ], diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index d1e7caed89..aa09c7061f 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -12,8 +12,6 @@ require 'active_record/test_case' require 'active_record/fixtures' require 'connection' -require 'cases/repair_helper' - begin require 'ruby-debug' rescue LoadError diff --git a/activerecord/test/cases/lifecycle_test.rb b/activerecord/test/cases/lifecycle_test.rb index 54fb3d8c39..ebf2e87cd5 100644 --- a/activerecord/test/cases/lifecycle_test.rb +++ b/activerecord/test/cases/lifecycle_test.rb @@ -1,4 +1,4 @@ -require "cases/helper" +require 'cases/helper' require 'models/topic' require 'models/developer' require 'models/reply' @@ -43,6 +43,11 @@ class TopicObserver < ActiveRecord::Observer def after_find(topic) @topic = topic end + + # Create an after_save callback, so a notify_observer hook is created + # on :topic. + def after_save(nothing) + end end class MinimalisticObserver < ActiveRecord::Observer @@ -159,18 +164,6 @@ class LifecycleTest < ActiveRecord::TestCase assert_equal topic, observer.topic end - def test_after_find_is_not_created_if_its_not_used - # use a fresh class so an observer can't have defined an - # after_find on it - model_class = Class.new(ActiveRecord::Base) - observer_class = Class.new(ActiveRecord::Observer) - observer_class.observe(model_class) - - observer = observer_class.instance - - assert !model_class.method_defined?(:after_find) - end - def test_after_find_is_not_clobbered_if_it_already_exists # use a fresh observer class so we can instantiate it (Observer is # a Singleton) diff --git a/activerecord/test/cases/repair_helper.rb b/activerecord/test/cases/repair_helper.rb deleted file mode 100644 index 80d04010d6..0000000000 --- a/activerecord/test/cases/repair_helper.rb +++ /dev/null @@ -1,46 +0,0 @@ -module ActiveRecord - module Testing - module RepairHelper - extend ActiveSupport::Concern - - module Toolbox - def self.record_validations(*model_classes) - model_classes.inject({}) do |repair, klass| - repair[klass] ||= {} - [:validate, :validate_on_create, :validate_on_update].each do |callback| - the_callback = klass.instance_variable_get("@#{callback.to_s}_callbacks") - repair[klass][callback] = (the_callback.nil? ? nil : the_callback.dup) - end - repair - end - end - - def self.reset_validations(recorded) - recorded.each do |klass, repairs| - [:validate, :validate_on_create, :validate_on_update].each do |callback| - klass.instance_variable_set("@#{callback.to_s}_callbacks", repairs[callback]) - end - end - end - end - - module ClassMethods - def repair_validations(*model_classes) - setup do - @validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes) - end - teardown do - ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(@validation_repairs) - end - end - end - - def repair_validations(*model_classes, &block) - validation_repairs = ActiveRecord::Testing::RepairHelper::Toolbox.record_validations(*model_classes) - return block.call - ensure - ActiveRecord::Testing::RepairHelper::Toolbox.reset_validations(validation_repairs) - end - end - end -end diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index f6533b5396..66baf1008a 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -382,19 +382,19 @@ class TransactionTest < ActiveRecord::TestCase private def add_exception_raising_after_save_callback_to_topic - Topic.class_eval { def after_save() raise "Make the transaction rollback" end } + Topic.class_eval "def after_save; raise 'Make the transaction rollback' end" end def remove_exception_raising_after_save_callback_to_topic - Topic.class_eval { remove_method :after_save } + Topic.class_eval "def after_save; end" end def add_exception_raising_after_create_callback_to_topic - Topic.class_eval { def after_create() raise "Make the transaction rollback" end } + Topic.class_eval "def after_create; raise 'Make the transaction rollback' end" end def remove_exception_raising_after_create_callback_to_topic - Topic.class_eval { remove_method :after_create } + Topic.class_eval "def after_create; end" end %w(validation save destroy).each do |filter| @@ -403,7 +403,7 @@ class TransactionTest < ActiveRecord::TestCase end define_method("remove_cancelling_before_#{filter}_with_db_side_effect_to_topic") do - Topic.class_eval "remove_method :before_#{filter}" + Topic.class_eval "def before_#{filter}; end" end end end diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb index 29c10de4fe..3794a0ebb9 100644 --- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb @@ -2,9 +2,9 @@ require "cases/helper" require 'models/topic' require 'models/reply' -class I18nGenerateMessageValidationTest < Test::Unit::TestCase +class I18nGenerateMessageValidationTest < ActiveRecord::TestCase def setup - reset_callbacks Topic + Topic.reset_callbacks(:validate) @topic = Topic.new I18n.backend.store_translations :'en', { :activerecord => { @@ -17,14 +17,6 @@ class I18nGenerateMessageValidationTest < Test::Unit::TestCase } end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value) def test_generate_message_inclusion_with_default_message assert_equal 'is not included in the list', @topic.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title') diff --git a/activerecord/test/cases/validations/i18n_validation_test.rb b/activerecord/test/cases/validations/i18n_validation_test.rb index 73d9c7249c..252138c0d6 100644 --- a/activerecord/test/cases/validations/i18n_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_validation_test.rb @@ -4,7 +4,7 @@ require 'models/reply' class I18nValidationTest < ActiveRecord::TestCase def setup - reset_callbacks Topic + Topic.reset_callbacks(:validate) @topic = Topic.new @old_load_path, @old_backend = I18n.load_path, I18n.backend I18n.load_path.clear @@ -13,7 +13,7 @@ class I18nValidationTest < ActiveRecord::TestCase end def teardown - reset_callbacks Topic + Topic.reset_callbacks(:validate) I18n.load_path.replace @old_load_path I18n.backend = @old_backend end @@ -30,14 +30,6 @@ class I18nValidationTest < ActiveRecord::TestCase end end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated assert_not_deprecated do default = "%s interpolation syntax was deprecated" @@ -710,9 +702,9 @@ class I18nValidationTest < ActiveRecord::TestCase end end -class ActiveRecordValidationsGenerateMessageI18nTests < ActiveSupport::TestCase +class ActiveRecordValidationsGenerateMessageI18nTests < ActiveRecord::TestCase + def setup - reset_callbacks Topic @topic = Topic.new I18n.backend.store_translations :'en', { :activerecord => { @@ -743,14 +735,6 @@ class ActiveRecordValidationsGenerateMessageI18nTests < ActiveSupport::TestCase } end - def reset_callbacks(*models) - models.each do |model| - model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new) - end - end - # validates_inclusion_of: generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value) def test_generate_message_inclusion_with_default_message assert_equal 'is not included in the list', @topic.errors.generate_message(:title, :inclusion, :default => nil, :value => 'title') diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index a4e874e5e6..6fd7fe6a21 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -161,12 +161,9 @@ class ValidationsTest < ActiveRecord::TestCase end def test_validates_acceptance_of_as_database_column - repair_validations(Reply) do - Reply.validates_acceptance_of(:author_name) - - reply = Reply.create("author_name" => "Dan Brown") - assert_equal "Dan Brown", reply["author_name"] - end + Topic.validates_acceptance_of(:author_name) + topic = Topic.create("author_name" => "Dan Brown") + assert_equal "Dan Brown", topic["author_name"] end def test_deprecated_validation_instance_methods -- cgit v1.2.3