Skip to content

Commit a59db85

Browse files
authored
Merge pull request rails#54665 from bensheldon/validation_callbacks_except_on
Add `except_on:` option for validation callbacks
2 parents 6411dbb + 87be3c3 commit a59db85

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

activemodel/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Add `except_on:` option for validation callbacks.
2+
3+
*Ben Sheldon*
4+
15
* Backport `ActiveRecord::Normalization` to `ActiveModel::Attributes::Normalization`
26

37
```ruby

activemodel/lib/active_model/validations/callbacks.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ def set_options_for_callback(options)
106106
*options[:if]
107107
]
108108
end
109+
110+
if options.key?(:except_on)
111+
options[:except_on] = Array(options[:except_on])
112+
options[:unless] = [
113+
->(o) {
114+
options[:except_on].intersect?(Array(o.validation_context))
115+
},
116+
*options[:unless]
117+
]
118+
end
109119
end
110120
end
111121

activemodel/test/cases/validations/callbacks_test.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,17 @@ def set_after_validation_marker; history << "after_validation_marker" ; end
6262
class DogValidatorWithOnMultipleCondition < Dog
6363
before_validation :set_before_validation_marker_on_context_a, on: :context_a
6464
before_validation :set_before_validation_marker_on_context_b, on: :context_b
65+
before_validation :set_before_validation_marker_except_on_context_a, except_on: :context_a
6566
after_validation :set_after_validation_marker_on_context_a, on: :context_a
6667
after_validation :set_after_validation_marker_on_context_b, on: :context_b
68+
after_validation :set_after_validation_marker_except_on_context_a, except_on: :context_a
6769

6870
def set_before_validation_marker_on_context_a; history << "before_validation_marker on context_a"; end
6971
def set_before_validation_marker_on_context_b; history << "before_validation_marker on context_b"; end
72+
def set_before_validation_marker_except_on_context_a; history << "before_validation_marker except on context_a"; end
7073
def set_after_validation_marker_on_context_a; history << "after_validation_marker on context_a" ; end
7174
def set_after_validation_marker_on_context_b; history << "after_validation_marker on context_b" ; end
75+
def set_after_validation_marker_except_on_context_a; history << "after_validation_marker except on context_a" ; end
7276
end
7377

7478
class DogValidatorWithIfCondition < Dog
@@ -117,7 +121,12 @@ def test_on_multiple_condition_is_respected_for_validation_with_matching_context
117121

118122
d = DogValidatorWithOnMultipleCondition.new
119123
d.valid?(:context_b)
120-
assert_equal ["before_validation_marker on context_b", "after_validation_marker on context_b"], d.history
124+
assert_equal [
125+
"before_validation_marker on context_b",
126+
"before_validation_marker except on context_a",
127+
"after_validation_marker on context_b",
128+
"after_validation_marker except on context_a"
129+
], d.history
121130

122131
d = DogValidatorWithOnMultipleCondition.new
123132
d.valid?([:context_a, :context_b])
@@ -132,13 +141,13 @@ def test_on_multiple_condition_is_respected_for_validation_with_matching_context
132141
def test_on_multiple_condition_is_respected_for_validation_without_matching_context
133142
d = DogValidatorWithOnMultipleCondition.new
134143
d.valid?(:save)
135-
assert_equal [], d.history
144+
assert_equal ["before_validation_marker except on context_a", "after_validation_marker except on context_a"], d.history
136145
end
137146

138147
def test_on_multiple_condition_is_respected_for_validation_without_context
139148
d = DogValidatorWithOnMultipleCondition.new
140149
d.valid?
141-
assert_equal [], d.history
150+
assert_equal ["before_validation_marker except on context_a", "after_validation_marker except on context_a"], d.history
142151
end
143152

144153
def test_before_validation_and_after_validation_callbacks_should_be_called

0 commit comments

Comments
 (0)