Skip to content

Commit b1fd934

Browse files
authored
Merge pull request rails#46238 from austenmadden/resolve-validates-associated-ignores-contexts
Pass validation_context to validates_associated
2 parents 4646b00 + e1e7981 commit b1fd934

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

activerecord/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
* Validate using `:on` option when using `validates_associated`
2+
3+
Fixes an issue where `validates_associated` `:on` option wasn't respected
4+
when validated associated records.
5+
6+
*Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
7+
18
* Allow overriding SQLite defaults from `database.yml`
29

310
Any PRAGMA configuration set under the `pragmas` key in the configuration file take precedence over Rails' defaults, and additional PRAGMAs can be set as well.

activerecord/lib/active_record/autosave_association.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,6 @@ def compute_primary_key(reflection, record)
547547
end
548548
end
549549

550-
def custom_validation_context?
551-
validation_context && [:create, :update].exclude?(validation_context)
552-
end
553-
554550
def _ensure_no_duplicate_errors
555551
errors.uniq!
556552
end

activerecord/lib/active_record/validations.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ def valid?(context = nil)
7474

7575
alias_method :validate, :valid?
7676

77+
def custom_validation_context? # :nodoc:
78+
validation_context && [:create, :update].exclude?(validation_context)
79+
end
80+
7781
private
7882
def default_validation_context
7983
new_record? ? :create : :update

activerecord/lib/active_record/validations/associated.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,20 @@ module ActiveRecord
44
module Validations
55
class AssociatedValidator < ActiveModel::EachValidator # :nodoc:
66
def validate_each(record, attribute, value)
7-
if Array(value).reject { |r| valid_object?(r) }.any?
7+
context = record_validation_context_for_association(record)
8+
9+
if Array(value).reject { |association| valid_object?(association, context) }.any?
810
record.errors.add(attribute, :invalid, **options.merge(value: value))
911
end
1012
end
1113

1214
private
13-
def valid_object?(record)
14-
(record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?
15+
def valid_object?(record, context)
16+
(record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?(context)
17+
end
18+
19+
def record_validation_context_for_association(record)
20+
record.custom_validation_context? ? record.validation_context : nil
1521
end
1622
end
1723

activerecord/test/cases/validations/association_validation_test.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_validates_associated_marked_for_destruction
4949

5050
def test_validates_associated_without_marked_for_destruction
5151
reply = Class.new do
52-
def valid?
52+
def valid?(context = nil)
5353
true
5454
end
5555
end
@@ -96,4 +96,26 @@ def test_validates_presence_of_belongs_to_association__existing_parent
9696
assert_predicate interest, :valid?, "Expected interest to be valid, but was not. Interest should have a human object associated"
9797
end
9898
end
99+
100+
def test_validates_associated_with_custom_context
101+
Reply.validates_associated :topic, on: :custom
102+
Topic.validates_presence_of :content, on: :custom
103+
r = Reply.create("title" => "A reply", "content" => "with content!")
104+
r.topic = Topic.create("title" => "uhohuhoh")
105+
assert_predicate r, :valid?
106+
assert_not r.valid?(:custom)
107+
assert_equal ["is invalid"], r.errors[:topic]
108+
end
109+
110+
def test_validates_associated_with_create_context
111+
Reply.validates_associated :topic, on: :create
112+
Topic.validates_presence_of :content, on: :create
113+
t = Topic.create(title: "uhoh", content: "stuff")
114+
t.update!(content: nil)
115+
# NOTE: Does not pass along :create context from reply to Topic validation.
116+
r = t.replies.create(title: "A reply", content: "with content!")
117+
118+
assert_predicate t, :valid?
119+
assert_predicate r, :valid?
120+
end
99121
end

0 commit comments

Comments
 (0)