diff options
11 files changed, 66 insertions, 26 deletions
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb index bd05d1014c..7f39a189e4 100644 --- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb +++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb @@ -37,7 +37,7 @@ module ActiveRecord if force record.save! else - return false unless record.save(validate) + return false unless record.save(:validate => validate) end end diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index d3336cf2d2..146a6ca55f 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -58,7 +58,7 @@ module ActiveRecord def insert_record(record, force = false, validate = true) set_belongs_to_association_for(record) - force ? record.save! : record.save(validate) + force ? record.save! : record.save(:validate => validate) end # Deletes the records according to the <tt>:dependent</tt> option. diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index 387b85aacd..bd2acd4340 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -60,7 +60,7 @@ module ActiveRecord if force record.save! else - return false unless record.save(validate) + return false unless record.save(:validate => validate) end end diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index e178cb4ef2..325a8aa7ec 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -116,14 +116,14 @@ module ActiveRecord # post = Post.find(1) # post.author.name = '' # post.save # => false - # post.errors # => #<ActiveRecord::Errors:0x174498c @errors={"author_name"=>["can't be blank"]}, @base=#<Post ...>> + # post.errors # => #<ActiveRecord::Errors:0x174498c @errors={"author.name"=>["can't be blank"]}, @base=#<Post ...>> # # No validations will be performed on the associated models when validations # are skipped for the parent: # # post = Post.find(1) # post.author.name = '' - # post.save(false) # => true + # post.save(:validate => false) # => true module AutosaveAssociation extend ActiveSupport::Concern @@ -302,7 +302,7 @@ module ActiveRecord association.send(:insert_record, record) end elsif autosave - saved = record.save(false) + saved = record.save(:validate => false) end raise ActiveRecord::Rollback if saved == false @@ -332,7 +332,7 @@ module ActiveRecord key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id if autosave != false && (new_record? || association.new_record? || association[reflection.primary_key_name] != key || autosave) association[reflection.primary_key_name] = key - saved = association.save(!autosave) + saved = association.save(:validate => !autosave) raise ActiveRecord::Rollback if !saved && autosave saved end @@ -355,7 +355,7 @@ module ActiveRecord if autosave && association.marked_for_destruction? association.destroy elsif autosave != false - saved = association.save(!autosave) if association.new_record? || autosave + saved = association.save(:validate => !autosave) if association.new_record? || autosave if association.updated? association_id = association.send(reflection.options[:primary_key] || :id) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 4ee9887186..06244d1132 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2136,16 +2136,16 @@ module ActiveRecord #:nodoc: end # :call-seq: - # save(perform_validation = true) + # save(options) # # Saves the model. # # If the model is new a record gets created in the database, otherwise # the existing record gets updated. # - # If +perform_validation+ is true validations run. If any of them fail - # the action is cancelled and +save+ returns +false+. If the flag is - # false validations are bypassed altogether. See + # By default, save always run validations. If any of them fail the action + # is cancelled and +save+ returns +false+. However, if you supply + # :validate => false, validations are bypassed altogether. See # ActiveRecord::Validations for more information. # # There's a series of callbacks associated with +save+. If any of the @@ -2220,7 +2220,7 @@ module ActiveRecord #:nodoc: # in Base is replaced with this when the validations module is mixed in, which it is by default. def update_attribute(name, value) send(name.to_s + '=', value) - save(false) + save(:validate => false) end # Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 4f8ccdd40e..cf0fe8934d 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -192,8 +192,8 @@ module ActiveRecord with_transaction_returning_status(:destroy_without_transactions) end - def save_with_transactions(perform_validation = true) #:nodoc: - rollback_active_record_state! { with_transaction_returning_status(:save_without_transactions, perform_validation) } + def save_with_transactions(*args) #:nodoc: + rollback_active_record_state! { with_transaction_returning_status(:save_without_transactions, *args) } end def save_with_transactions! #:nodoc: diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index d5adcba3ba..a9743aa1ea 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -42,7 +42,17 @@ module ActiveRecord module InstanceMethods # The validation process on save can be skipped by passing false. The regular Base#save method is # replaced with this when the validations module is mixed in, which it is by default. - def save_with_validation(perform_validation = true) + def save_with_validation(options=nil) + perform_validation = case options + when NilClass + true + when Hash + options[:validate] != false + else + ActiveSupport::Deprecation.warn "save(#{options}) is deprecated, please give save(:validate => #{options}) instead", caller + options + end + if perform_validation && valid? || !perform_validation save_without_validation else diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index cc36a6dc5b..cc5460ddb7 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -805,7 +805,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase def test_should_still_allow_to_bypass_validations_on_the_associated_model @pirate.catchphrase = '' @pirate.ship.name = '' - @pirate.save(false) + @pirate.save(:validate => false) # Oracle saves empty string as NULL if current_adapter?(:OracleAdapter) assert_equal [nil, nil], [@pirate.reload.catchphrase, @pirate.ship.name] @@ -820,7 +820,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase @pirate.catchphrase = '' @pirate.ship.name = '' @pirate.ship.parts.each { |part| part.name = '' } - @pirate.save(false) + @pirate.save(:validate => false) values = [@pirate.reload.catchphrase, @pirate.ship.name, *@pirate.ship.parts.map(&:name)] # Oracle saves empty string as NULL @@ -917,7 +917,7 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase def test_should_still_allow_to_bypass_validations_on_the_associated_model @ship.pirate.catchphrase = '' @ship.name = '' - @ship.save(false) + @ship.save(:validate => false) # Oracle saves empty string as NULL if current_adapter?(:OracleAdapter) assert_equal [nil, nil], [@ship.reload.name, @ship.pirate.catchphrase] @@ -1029,7 +1029,7 @@ module AutosaveAssociationOnACollectionAssociationTests @pirate.catchphrase = '' @pirate.send(@association_name).each { |child| child.name = '' } - assert @pirate.save(false) + assert @pirate.save(:validate => false) # Oracle saves empty string as NULL if current_adapter?(:OracleAdapter) assert_equal [nil, nil, nil], [ @@ -1049,14 +1049,14 @@ module AutosaveAssociationOnACollectionAssociationTests def test_should_validation_the_associated_models_on_create assert_no_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count") do 2.times { @pirate.send(@association_name).build } - @pirate.save(true) + @pirate.save end end def test_should_allow_to_bypass_validations_on_the_associated_models_on_create assert_difference("#{ @association_name == :birds ? 'Bird' : 'Parrot' }.count", +2) do 2.times { @pirate.send(@association_name).build } - @pirate.save(false) + @pirate.save(:validate => false) end end diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb index 3a1d5ae212..8314f880be 100644 --- a/activerecord/test/cases/validations_test.rb +++ b/activerecord/test/cases/validations_test.rb @@ -124,7 +124,15 @@ class ValidationsTest < ActiveRecord::TestCase def test_create_without_validation reply = WrongReply.new assert !reply.save - assert reply.save(false) + assert reply.save(:validate => false) + end + + def test_deprecated_create_without_validation + reply = WrongReply.new + assert !reply.save + assert_deprecated do + assert reply.save(false) + end end def test_create_without_validation_bang diff --git a/activeresource/lib/active_resource/validations.rb b/activeresource/lib/active_resource/validations.rb index 67b69fa505..7b2382bd8c 100644 --- a/activeresource/lib/active_resource/validations.rb +++ b/activeresource/lib/active_resource/validations.rb @@ -58,9 +58,8 @@ module ActiveResource # person.save # => true (and person is now saved to the remote service) # module Validations - extend ActiveSupport::Concern + extend ActiveSupport::Concern include ActiveModel::Validations - extend ActiveModel::Validations::ClassMethods included do alias_method_chain :save, :validation @@ -68,7 +67,17 @@ module ActiveResource # Validate a resource and save (POST) it to the remote web service. # If any local validations fail - the save (POST) will not be attempted. - def save_with_validation(perform_validation = true) + def save_with_validation(options=nil) + perform_validation = case options + when Hash + options[:validate] != false + when NilClass + true + else + ActiveSupport::Deprecation.warn "save(#{options}) is deprecated, please give save(:validate => #{options}) instead", caller + options + end + # clear the remote validations so they don't interfere with the local # ones. Otherwise we get an endless loop and can never change the # fields so as to make the resource valid diff --git a/activeresource/test/cases/validations_test.rb b/activeresource/test/cases/validations_test.rb index c05f625fb7..82546424f2 100644 --- a/activeresource/test/cases/validations_test.rb +++ b/activeresource/test/cases/validations_test.rb @@ -30,6 +30,19 @@ class ValidationsTest < ActiveModel::TestCase assert_raise(ActiveResource::ResourceInvalid) { p.save! } end + def test_save_without_validation + p = new_project(:name => nil) + assert !p.save + assert p.save(:validate => false) + end + + def test_deprecated_save_without_validation + p = new_project(:name => nil) + assert !p.save + assert_deprecated do + assert p.save(false) + end + end def test_validate_callback # we have a callback ensuring the description is longer than three letters |