aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Rohrer <matt@prognostikos.com>2017-09-21 15:39:49 +0200
committerMatt Rohrer <matt@prognostikos.com>2017-10-26 10:01:06 +0200
commitb8b089ef11300fab4625011b942ee4a1fbbdbbbd (patch)
tree2e7aae2d26e56036acced292301ff7fd8326b9b6
parent8cd143900978902ed9bbba10b34099a3140de5c6 (diff)
downloadrails-b8b089ef11300fab4625011b942ee4a1fbbdbbbd.tar.gz
rails-b8b089ef11300fab4625011b942ee4a1fbbdbbbd.tar.bz2
rails-b8b089ef11300fab4625011b942ee4a1fbbdbbbd.zip
Allow passing a Proc or Symbol as an argument to length validator values
This brings the Length validator in line with the Numericality validator, which currently supports Proc & Symbol arguments
-rw-r--r--activemodel/CHANGELOG.md4
-rw-r--r--activemodel/lib/active_model/validations/length.rb10
-rw-r--r--activemodel/test/cases/validations/length_validation_test.rb31
3 files changed, 43 insertions, 2 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 048c43f2c4..82e3a7f4dd 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Allow passing a Proc or Symbol to length validator options.
+
+ *Matt Rohrer*
+
* Add method `#merge!` for `ActiveModel::Errors`.
*Jahfer Husain*
diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb
index d1a4197286..d6c80b2c5d 100644
--- a/activemodel/lib/active_model/validations/length.rb
+++ b/activemodel/lib/active_model/validations/length.rb
@@ -31,8 +31,8 @@ module ActiveModel
keys.each do |key|
value = options[key]
- unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY
- raise ArgumentError, ":#{key} must be a nonnegative Integer or Infinity"
+ unless (value.is_a?(Integer) && value >= 0) || value == Float::INFINITY || value.is_a?(Symbol) || value.is_a?(Proc)
+ raise ArgumentError, ":#{key} must be a nonnegative Integer, Infinity, Symbol, or Proc"
end
end
end
@@ -45,6 +45,12 @@ module ActiveModel
next unless check_value = options[key]
if !value.nil? || skip_nil_check?(key)
+ case check_value
+ when Proc
+ check_value = check_value.call(record)
+ when Symbol
+ check_value = record.send(check_value)
+ end
next if value_length.send(validity_check, check_value)
end
diff --git a/activemodel/test/cases/validations/length_validation_test.rb b/activemodel/test/cases/validations/length_validation_test.rb
index a0d8e058f5..42f76f3e3c 100644
--- a/activemodel/test/cases/validations/length_validation_test.rb
+++ b/activemodel/test/cases/validations/length_validation_test.rb
@@ -410,4 +410,35 @@ class LengthValidationTest < ActiveModel::TestCase
assert Topic.new("title" => "david").valid?
assert Topic.new("title" => "david2").invalid?
end
+
+ def test_validates_length_of_using_proc_as_maximum
+ Topic.validates_length_of :title, maximum: ->(model) { 5 }
+
+ t = Topic.new("title" => "valid", "content" => "whatever")
+ assert t.valid?
+
+ t.title = "notvalid"
+ assert t.invalid?
+ assert t.errors[:title].any?
+ assert_equal ["is too long (maximum is 5 characters)"], t.errors[:title]
+
+ t.title = ""
+ assert t.valid?
+ end
+
+ def test_validates_length_of_using_proc_as_maximum_with_model_method
+ Topic.send(:define_method, :max_title_length, lambda { 5 })
+ Topic.validates_length_of :title, maximum: Proc.new(&:max_title_length)
+
+ t = Topic.new("title" => "valid", "content" => "whatever")
+ assert t.valid?
+
+ t.title = "notvalid"
+ assert t.invalid?
+ assert t.errors[:title].any?
+ assert_equal ["is too long (maximum is 5 characters)"], t.errors[:title]
+
+ t.title = ""
+ assert t.valid?
+ end
end