From 05215ddebba54da0ba54be7968df6030d53d4a06 Mon Sep 17 00:00:00 2001 From: Fred Wu Date: Tue, 24 Aug 2010 17:48:54 +1000 Subject: [PATCH] Added ':model_callbacks' option to :save, :destroy and :touch. So you can do 'user.save(:callbacks => false)' to disable model callbacks. --- activerecord/lib/active_record/callbacks.rb | 30 ++++++++++++++------- activerecord/lib/active_record/persistence.rb | 12 ++++---- activerecord/test/cases/callbacks_test.rb | 35 +++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index a31973d..6c80cb2 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -256,12 +256,16 @@ module ActiveRecord end end - def destroy #:nodoc: - _run_destroy_callbacks { super } + def save(*args) + super end - def touch(*) #:nodoc: - _run_touch_callbacks { super } + def destroy(options={}) #:nodoc: + perform_model_callbacks?(options) ? _run_destroy_callbacks { super() } : super() + end + + def touch(options={}) #:nodoc: + perform_model_callbacks?(options) ? _run_touch_callbacks { super() } : super() end def deprecated_callback_method(symbol) #:nodoc: @@ -271,18 +275,24 @@ module ActiveRecord end end + protected + + def perform_model_callbacks?(options={}) + options.key?(:model_callbacks) ? !!options[:model_callbacks] : true + end + private - def create_or_update #:nodoc: - _run_save_callbacks { super } + def create_or_update(options={}) #:nodoc: + perform_model_callbacks?(options) ? _run_save_callbacks { super() } : super() end - def create #:nodoc: - _run_create_callbacks { super } + def create(options={}) #:nodoc: + perform_model_callbacks?(options) ? _run_create_callbacks { super() } : super() end - def update(*) #:nodoc: - _run_update_callbacks { super } + def update(attribute_names = @attributes.keys, options={}) #:nodoc: + perform_model_callbacks?(options) ? _run_update_callbacks { super(attribute_names) } : super(attribute_names) end end end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 0188972..bc6f0be 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -35,8 +35,8 @@ module ActiveRecord # before_* callbacks return +false+ the action is cancelled and # +save+ returns +false+. See ActiveRecord::Callbacks for further # details. - def save(*) - create_or_update + def save(*args) + create_or_update(*args) end # Saves the model. @@ -52,8 +52,8 @@ module ActiveRecord # the before_* callbacks return +false+ the action is cancelled # and save! raises ActiveRecord::RecordNotSaved. See # ActiveRecord::Callbacks for further details. - def save!(*) - create_or_update || raise(RecordNotSaved) + def save!(*args) + create_or_update(*args) || raise(RecordNotSaved) end # Deletes the record in the database and freezes this instance to @@ -110,11 +110,11 @@ module ActiveRecord # * updated_at/updated_on column is updated if that column is available. # * Updates all the attributes that are dirty in this object. # - def update_attribute(name, value) + def update_attribute(name, value, options={}) name = name.to_s raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name) send("#{name}=", value) - save(:validate => false) + save({ :validate => false }.merge!(options)) end # Updates the attributes of the model from the passed-in hash and saves the diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 8a84f19..2ac6cbc 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -87,6 +87,11 @@ class ImmutableDeveloper < ActiveRecord::Base before_save :cancel before_destroy :cancel + def initialize + super + @cancelled ||= false + end + def cancelled? @cancelled == true end @@ -482,4 +487,34 @@ class CallbacksTest < ActiveRecord::TestCase assert child.after_save_called end + def test_model_callbacks_enabled + david = ImmutableDeveloper.new + david.save + assert_equal true, david.cancelled? + end + + def test_model_callbacks_enabled_with_set_options + david = ImmutableDeveloper.new + david.save(:model_callbacks => true) + assert_equal true, david.cancelled? + end + + def test_model_callbacks_disabled + david = ImmutableDeveloper.new + david.save(:model_callbacks => false) + assert_equal false, david.cancelled? + end + + def test_callbacks_for_validations_enabled + david = ParentDeveloper.new + david.save + assert_equal true, david.after_save_called + end + + def test_callbacks_for_validations_disabled + david = ParentDeveloper.new + david.save(:model_callbacks => false) + assert_equal true, david.after_save_called + end + end -- 1.6.4.2