Skip to content

Commit d3868c7

Browse files
committed
Fix required on belongs_to for rails 7.1+
1 parent 2df5c7d commit d3868c7

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

lib/simple_form/helpers/validators.rb

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,46 @@ def valid_validator?(validator)
2121
end
2222

2323
def conditional_validators?(validator)
24-
validator.options.include?(:if) || validator.options.include?(:unless)
24+
if_condition = validator.options[:if]
25+
unless_condition = validator.options[:unless]
26+
27+
return false if if_condition.nil? && unless_condition.nil?
28+
29+
conditional = false
30+
31+
if if_condition
32+
conditions = Array(if_condition)
33+
conditional = conditions.any? { |c| !resolve_if_condition(c) }
34+
end
35+
36+
if !conditional && unless_condition
37+
conditions = Array(unless_condition)
38+
conditional = conditions.any? { |c| resolve_if_condition(c) }
39+
end
40+
41+
conditional
42+
# If evaluating the condition fails (e.g., the condition references a method
43+
# the object doesn't have, or a callable with unexpected arity), fall back to
44+
# treating the validator as conditional and skipping it.
45+
rescue NoMethodError, ArgumentError
46+
true
47+
end
48+
49+
def resolve_if_condition(condition)
50+
case condition
51+
when Symbol
52+
object.send(condition)
53+
else
54+
if condition.respond_to?(:call)
55+
if condition.is_a?(Proc) && condition.arity == 0
56+
condition.call
57+
else
58+
condition.call(object)
59+
end
60+
else
61+
condition
62+
end
63+
end
2564
end
2665

2766
def action_validator_match?(validator)

test/inputs/required_test.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,32 @@ class RequiredTest < ActionView::TestCase
8282
end
8383

8484
# VALIDATORS :if :unless
85-
test 'builder input does not be required when ActiveModel::Validations is included and if option is present' do
85+
test 'builder input is required when if condition is present and evaluates to true' do
86+
with_form_for @validating_user, :age
87+
assert_select 'input.required[required]#validating_user_age'
88+
end
89+
90+
test 'builder input is not required when if condition is present and evaluates to false' do
91+
@validating_user.name = nil
8692
with_form_for @validating_user, :age
8793
assert_no_select 'input.required'
8894
assert_no_select 'input[required]'
8995
assert_select 'input.optional#validating_user_age'
9096
end
9197

92-
test 'builder input does not be required when ActiveModel::Validations is included and unless option is present' do
98+
test 'builder input is not required when unless condition is present and evaluates to true' do
9399
with_form_for @validating_user, :amount
94100
assert_no_select 'input.required'
95101
assert_no_select 'input[required]'
96102
assert_select 'input.optional#validating_user_amount'
97103
end
98104

105+
test 'builder input is required when unless condition is present and evaluates to false' do
106+
@validating_user.age = nil
107+
with_form_for @validating_user, :amount
108+
assert_select 'input.required[required]#validating_user_amount'
109+
end
110+
99111
# VALIDATORS :on
100112
test 'builder input is required when validation is on create and is not persisted' do
101113
@validating_user.new_record!

0 commit comments

Comments
 (0)