From 85465ed3e6c582d25f0c8fafe21f7a2c182c2f67 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 30 Jan 2015 07:26:33 -0700 Subject: Always perform validations on nested attribute associations Collection associations would have already been validated, but singular associations were not. Fixes #18735. --- activerecord/lib/active_record/autosave_association.rb | 16 ++++++++++++---- activerecord/lib/active_record/nested_attributes.rb | 1 + activerecord/test/cases/nested_attributes_test.rb | 7 +++++++ activerecord/test/models/ship_part.rb | 3 ++- 4 files changed, 22 insertions(+), 5 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index fcaaffb852..0792d19c3e 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -177,10 +177,8 @@ module ActiveRecord # before actually defining them. def add_autosave_association_callbacks(reflection) save_method = :"autosave_associated_records_for_#{reflection.name}" - validation_method = :"validate_associated_records_for_#{reflection.name}" - collection = reflection.collection? - if collection + if reflection.collection? before_save :before_save_collection_association define_non_cyclic_method(save_method) { save_collection_association(reflection) } @@ -204,8 +202,18 @@ module ActiveRecord before_save save_method end + define_autosave_validation_callbacks(reflection) + end + + def define_autosave_validation_callbacks(reflection) + validation_method = :"validate_associated_records_for_#{reflection.name}" if reflection.validate? && !method_defined?(validation_method) - method = (collection ? :validate_collection_association : :validate_single_association) + if reflection.collection? + method = :validate_collection_association + else + method = :validate_single_association + end + define_non_cyclic_method(validation_method) do send(method, reflection) # TODO: remove the following line as soon as the return value of diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 919bbfa649..117a128579 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -312,6 +312,7 @@ module ActiveRecord attr_names.each do |association_name| if reflection = _reflect_on_association(association_name) reflection.autosave = true + define_autosave_validation_callbacks(reflection) nested_attributes_options = self.nested_attributes_options.dup nested_attributes_options[association_name.to_sym] = options diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index a9e93ad1b6..198cd6f341 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -1047,4 +1047,11 @@ class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveR ship.save! end end + + test "nested singular associations are validated" do + part = ShipPart.new(name: "Stern", ship_attributes: { name: nil }) + + assert_not part.valid? + assert_equal ["Ship name can't be blank"], part.errors.full_messages + end end diff --git a/activerecord/test/models/ship_part.rb b/activerecord/test/models/ship_part.rb index b6a8a506b4..05c65f8a4a 100644 --- a/activerecord/test/models/ship_part.rb +++ b/activerecord/test/models/ship_part.rb @@ -2,6 +2,7 @@ class ShipPart < ActiveRecord::Base belongs_to :ship has_many :trinkets, :class_name => "Treasure", :as => :looter accepts_nested_attributes_for :trinkets, :allow_destroy => true + accepts_nested_attributes_for :ship validates_presence_of :name -end \ No newline at end of file +end -- cgit v1.2.3