diff --git a/.rubocop.yml b/.rubocop.yml index 04770ae7..9c749412 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -27,7 +27,7 @@ Layout/LineLength: Enabled: false Metrics/AbcSize: - Max: 21.91 + Max: 24.52 Metrics/BlockLength: Exclude: @@ -87,3 +87,6 @@ Style/FormatStringToken: Style/IfUnlessModifier: Enabled: false + +Style/NumericPredicate: + Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index b0aad575..7784b964 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * [FEATURE] Drop Internet Explorer and other older browsers support * [FEATURE] Drop Ruby < 3.1 * [FEATURE] Drop jQuery < 3.7.1 Compatibility +* [BUGFIX] Allow `proc` values in length validator options * [ENHANCEMENT] Update QUnit to 2.24.3 * [ENHANCEMENT] Test against Ruby 3.4 diff --git a/lib/client_side_validations/active_model.rb b/lib/client_side_validations/active_model.rb index d9a1bf07..f6ac2675 100644 --- a/lib/client_side_validations/active_model.rb +++ b/lib/client_side_validations/active_model.rb @@ -45,6 +45,14 @@ def message_type def callbacks_options ::ActiveModel::Error::CALLBACKS_OPTIONS end + + def resolve_proc(value, object) + if value.arity == 0 + value.call + else + value.call(object) + end + end end module Validations @@ -172,7 +180,7 @@ def client_side_hash(model, attribute, force = nil) if options[:in].respond_to?(:call) return unless force - options[:in] = options[:in].call(model) + options[:in] = resolve_proc(options[:in], model) end hash = build_client_side_hash(model, attribute, options) diff --git a/lib/client_side_validations/active_model/format.rb b/lib/client_side_validations/active_model/format.rb index c6c7ebbd..3d7558e1 100644 --- a/lib/client_side_validations/active_model/format.rb +++ b/lib/client_side_validations/active_model/format.rb @@ -8,12 +8,12 @@ def client_side_hash(model, attribute, force = nil) if options[:with].respond_to?(:call) return unless force - options[:with] = options[:with].call(model) + options[:with] = resolve_proc(options[:with], model) build_client_side_hash(model, attribute, options) elsif options[:without].respond_to?(:call) return unless force - options[:without] = options[:without].call(model) + options[:without] = resolve_proc(options[:without], model) build_client_side_hash(model, attribute, options) else super diff --git a/lib/client_side_validations/active_model/length.rb b/lib/client_side_validations/active_model/length.rb index c7275b04..8643e3a3 100644 --- a/lib/client_side_validations/active_model/length.rb +++ b/lib/client_side_validations/active_model/length.rb @@ -3,7 +3,7 @@ module ClientSideValidations module ActiveModel module Length - def client_side_hash(model, attribute, _force = nil) + def client_side_hash(model, attribute, force = nil) options = self.options.dup hash = options_hash(options) @@ -11,6 +11,12 @@ def client_side_hash(model, attribute, _force = nil) count = options[option] next unless count + if count.respond_to?(:call) + next unless force + + count = resolve_proc(count, model) + end + options[:message] = options[message_type] if options[message_type].present? options.delete(:message) if options[:message].nil? hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(count: count)) diff --git a/lib/client_side_validations/active_model/numericality.rb b/lib/client_side_validations/active_model/numericality.rb index 5690dbe2..14b6e197 100644 --- a/lib/client_side_validations/active_model/numericality.rb +++ b/lib/client_side_validations/active_model/numericality.rb @@ -23,7 +23,7 @@ def client_side_hash(model, attribute, force = nil) if count.respond_to?(:call) next unless force - count = count.call(model) + count = resolve_proc(count, model) end hash[:messages][option] = model.errors.generate_message(attribute, message_type, options.merge(count: count)) diff --git a/test/active_model/cases/test_length_validator.rb b/test/active_model/cases/test_length_validator.rb index 65a78bd9..9f966b30 100644 --- a/test/active_model/cases/test_length_validator.rb +++ b/test/active_model/cases/test_length_validator.rb @@ -70,5 +70,29 @@ def test_length_client_side_hash_with_range assert_equal expected_hash, LengthValidator.new(attributes: [:age], within: 5..10).client_side_hash(@person, :age) end + + def test_length_client_side_hash_with_minimum_and_maximum_proc_force + expected_hash = { + messages: { + minimum: 'is too short (minimum is 5 characters)', + maximum: 'is too long (maximum is 10 characters)' + }, + minimum: 5, + maximum: 10 + } + + assert_equal expected_hash, LengthValidator.new(attributes: [:age], minimum: proc { 5 }, maximum: proc { 10 }).client_side_hash(@person, :age, force: true) + end + + def test_length_client_side_hash_with_is_proc_force + expected_hash = { + messages: { + is: 'is the wrong length (should be 10 characters)' + }, + is: 10 + } + + assert_equal expected_hash, LengthValidator.new(attributes: [:age], is: proc { 10 }).client_side_hash(@person, :age, force: true) + end end end