Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Avoid infinite recursive validation when validate => true

#2183

An outgrowth of #2144 Don't autosave new_record associations. Since the solution to my problem was apparently "validate => true". This happens to be a problem for my situation.

I happen to be in a situation like this:


  def test_do_the_right_thing_on_validate
    Pirate.class_eval do
      belongs_to :parrot, :validate => true
    end
    Parrot.class_eval do
      has_and_belongs_to_many :pirates, :validate => true
    end
    
    pirate = Pirate.new(:catchphrase => "Figure out how to validate me please")
    pirate.parrot = Parrot.new
    pirate.parrot.pirates << pirate

    #because the parrot doesn't have a name, this save should fail invalid
    assert_raises(ActiveRecord::RecordInvalid){
      pirate.save!      
    }
  end

And, as you might have guessed, if you run this test....


  1) Failure:
test_do_the_right_thing_on_validate(TestStuff)
    [./test/cases/autosave_association_test.rb:883:in `test_do_the_right_thing_on_validate'
     ./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `__send__'
     ./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `run']:
<ActiveRecord::RecordInvalid> exception expected but was
Class: <SystemStackError>
Message: <"stack level too deep">
---Backtrace---
./test/cases/../../lib/active_record/callbacks.rb:312:in `valid?'
./test/cases/../../lib/active_record/associations/association_proxy.rb:221:in `send'
./test/cases/../../lib/active_record/associations/association_proxy.rb:221:in `method_missing'
./test/cases/../../lib/active_record/autosave_association.rb:249:in `association_valid?'
./test/cases/../../lib/active_record/autosave_association.rb:229:in `validate_single_association'
./test/cases/../../lib/active_record/autosave_association.rb:183:in `validate_associated_records_for_parrot'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:180:in `evaluate_method'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:180:in `evaluate_method'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:180:in `instance_eval'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:180:in `evaluate_method'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:166:in `call'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:90:in `run'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:90:in `each'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:90:in `send'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:90:in `run'
./test/cases/../../../activesupport/lib/active_support/callbacks.rb:276:in `run_callbacks'
./test/cases/../../lib/active_record/validations.rb:1029:in `valid_without_callbacks?'
./test/cases/../../lib/active_record/callbacks.rb:315:in `valid?'
...
./test/cases/../../lib/active_record/callbacks.rb:315:in `valid?'
./test/cases/../../lib/active_record/validations.rb:1018:in `save_without_dirty!'
./test/cases/../../lib/active_record/dirty.rb:87:in `save_without_transactions!'
./test/cases/../../lib/active_record/transactions.rb:200:in `save!'
./test/cases/../../lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'
./test/cases/../../lib/active_record/transactions.rb:182:in `transaction'
./test/cases/../../lib/active_record/transactions.rb:200:in `save!'
./test/cases/../../lib/active_record/transactions.rb:208:in `rollback_active_record_state!'
./test/cases/../../lib/active_record/transactions.rb:200:in `save!'
./test/cases/autosave_association_test.rb:884:in `test_do_the_right_thing_on_validate'
./test/cases/autosave_association_test.rb:883:in `test_do_the_right_thing_on_validate'
./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `__send__'
./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `run'
---------------

Reported by Jacob Burkhart · March 9th, 2009 @ 06:14 PM

State: invalid
Milestone: 2.x
Assigned to: Pratik Pratik
Importance: none

Activity

  1. Jacob Burkhart
    Jacob Burkhart
    • Title changed from Avoid recursive validation when validate => true to Avoid infinite recursive validation when validate => true

    March 9th, 2009 @ 06:15 PM

  2. Eloy Duran
    Eloy Duran
    • Assigned user set to Eloy Duran

    March 9th, 2009 @ 08:10 PM

  3. Pratik
    Pratik
    • Assigned user changed from Eloy Duran to Pratik
    • State changed from new to invalid

    I'd usually put :validate => false in one of the models and raise exception from an after_save callback if something didn't validate well and rely on transaction thingy to roll it all back.

    Thanks.

    March 10th, 2009 @ 11:35 AM