diff options
author | eileencodes <eileencodes@gmail.com> | 2015-01-10 16:46:57 -0500 |
---|---|---|
committer | eileencodes <eileencodes@gmail.com> | 2015-02-01 16:03:49 -0800 |
commit | 27aa4dda7d89ce7332e6d1f3266c3a0cf1c3fb9e (patch) | |
tree | f91555ce55e52110d6fc7df6401aa13e227137ee /activerecord/lib | |
parent | 226cd8a094c81edb72143173e4d0c88a2eb01d5f (diff) | |
download | rails-27aa4dda7d89ce7332e6d1f3266c3a0cf1c3fb9e.tar.gz rails-27aa4dda7d89ce7332e6d1f3266c3a0cf1c3fb9e.tar.bz2 rails-27aa4dda7d89ce7332e6d1f3266c3a0cf1c3fb9e.zip |
Fix validations on child record when record parent has validate: false
Fixes #17621. This 5 year old (or older) issue causes validations to fire
when a parent record has `validate: false` option and a child record is
saved. It's not the responsibility of the model to validate an
associated object unless the object was created or modified by the
parent.
Clean up tests related to validations
`assert_nothing_raised` is not benefiting us in these tests
Corrected spelling of "respects"
It's better to use `assert_not_operator` over `assert !r.valid`
Diffstat (limited to 'activerecord/lib')
-rw-r--r-- | activerecord/lib/active_record/validations/length.rb | 12 | ||||
-rw-r--r-- | activerecord/lib/active_record/validations/presence.rb | 1 | ||||
-rw-r--r-- | activerecord/lib/active_record/validations/uniqueness.rb | 1 |
3 files changed, 14 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/validations/length.rb b/activerecord/lib/active_record/validations/length.rb index ef5a6cbbe7..5991fbad8e 100644 --- a/activerecord/lib/active_record/validations/length.rb +++ b/activerecord/lib/active_record/validations/length.rb @@ -2,11 +2,23 @@ module ActiveRecord module Validations class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc: def validate_each(record, attribute, association_or_value) + return unless should_validate?(record) || associations_are_dirty?(record) if association_or_value.respond_to?(:loaded?) && association_or_value.loaded? association_or_value = association_or_value.target.reject(&:marked_for_destruction?) end super end + + def associations_are_dirty?(record) + attributes.any? do |attribute| + value = record.read_attribute_for_validation(attribute) + if value.respond_to?(:loaded?) && value.loaded? + value.target.any?(&:marked_for_destruction?) + else + false + end + end + end end module ClassMethods diff --git a/activerecord/lib/active_record/validations/presence.rb b/activerecord/lib/active_record/validations/presence.rb index 61b30749d9..75d5bd5a35 100644 --- a/activerecord/lib/active_record/validations/presence.rb +++ b/activerecord/lib/active_record/validations/presence.rb @@ -2,6 +2,7 @@ module ActiveRecord module Validations class PresenceValidator < ActiveModel::Validations::PresenceValidator # :nodoc: def validate(record) + return unless should_validate?(record) super attributes.each do |attribute| next unless record.class._reflect_on_association(attribute) diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 8f7a46f2c7..ad56f637e3 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -11,6 +11,7 @@ module ActiveRecord end def validate_each(record, attribute, value) + return unless should_validate?(record) finder_class = find_finder_class_for(record) table = finder_class.arel_table value = map_enum_attribute(finder_class, attribute, value) |