Skip to content

Commit 884a40e

Browse files
zzakbyroot
authored andcommitted
Avoid crash to validate circular autosave association
1 parent 71fc672 commit 884a40e

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

activerecord/lib/active_record/autosave_association.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ def association_valid?(association, record)
383383
end
384384

385385
if association.options[:autosave]
386+
return if equal?(record)
387+
386388
associated_errors.each { |error|
387389
errors.objects.append(
388390
Associations::NestedError.new(association, error)

activerecord/test/cases/autosave_association_test.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,35 @@ def test_valid_adding_with_validate_false
877877
assert_equal no_of_clients + 1, Client.count
878878
end
879879

880+
def test_circular_autosave_does_not_validate_children
881+
person = Class.new(ActiveRecord::Base) {
882+
self.table_name = "readers"
883+
validate :should_be_funny
884+
def self.name; "Reader"; end
885+
886+
attribute :catch_phrase, :string
887+
attribute :reader_id
888+
889+
has_many :children, autosave: true, anonymous_class: self
890+
belongs_to :parent, autosave: true, anonymous_class: self
891+
892+
private
893+
def should_be_funny
894+
unless catch_phrase == "funny"
895+
errors.add :base, "not funny"
896+
end
897+
end
898+
}
899+
c = person.new(catch_phrase: "boring")
900+
c.children << c
901+
c.post_id = 0
902+
c.person_id = 0
903+
c.save
904+
905+
assert_not_predicate c, :persisted?
906+
assert_not_predicate c, :valid?
907+
end
908+
880909
def test_parent_should_save_children_record_with_foreign_key_validation_set_in_before_save_callback
881910
company = NewlyContractedCompany.new(name: "test")
882911

0 commit comments

Comments
 (0)