diff options
-rw-r--r-- | activemodel/CHANGELOG.md | 4 | ||||
-rw-r--r-- | activemodel/lib/active_model/validations/length.rb | 10 | ||||
-rw-r--r-- | activemodel/test/cases/validations/length_validation_test.rb | 31 |
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 |