diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index a8f470397b3f81cd5bb1d1ba8ca1e784baff25c9..1916c3439a7c2ad83955de48e6bbd0be2aa80d2e 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,5 +1,11 @@ ## Rails 4.0.0 (unreleased) ## +* Changed inclusion and exclusion validators to accept a symbol for `:in` option. + + This allows to use dynamic inclusion/exclusion values using methods, besides the current lambda/proc support. + + *Gabriel Sobrinho* + * `AM::Validation#validates` ability to pass custom exception to `:strict` option. *Bogdan Gusiev* diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb index 643a6f2b7cff55c05a3aaf0f56410864a588bde3..cf1415b6c2a39aa4e2d7c914119006aa078e9af9 100644 --- a/activemodel/lib/active_model/validations/clusivity.rb +++ b/activemodel/lib/active_model/validations/clusivity.rb @@ -3,11 +3,11 @@ module ActiveModel module Validations module Clusivity #:nodoc: - ERROR_MESSAGE = "An object with the method #include? or a proc or lambda is required, " << + ERROR_MESSAGE = "An object with the method #include? or a proc, lambda or symbol is required, " << "and must be supplied as the :in (or :within) option of the configuration hash" def check_validity! - unless [:include?, :call].any?{ |method| delimiter.respond_to?(method) } + unless delimiter.respond_to?(:include?) || delimiter.respond_to?(:call) || delimiter.respond_to?(:to_sym) raise ArgumentError, ERROR_MESSAGE end end @@ -15,7 +15,14 @@ def check_validity! private def include?(record, value) - exclusions = delimiter.respond_to?(:call) ? delimiter.call(record) : delimiter + exclusions = if delimiter.respond_to?(:call) + delimiter.call(record) + elsif delimiter.respond_to?(:to_sym) + record.send(delimiter) + else + delimiter + end + exclusions.send(inclusion_method(exclusions), value) end diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb index dc3368c5694d9c2cb586605eef50f7efab72e174..3ec552c372945230fc1a8f7604f88092e8df9055 100644 --- a/activemodel/lib/active_model/validations/exclusion.rb +++ b/activemodel/lib/active_model/validations/exclusion.rb @@ -24,11 +24,12 @@ module HelperMethods # validates_exclusion_of :format, in: %w( mov avi ), message: "extension %{value} is not allowed" # validates_exclusion_of :password, in: ->(person) { [person.username, person.first_name] }, # message: 'should not be the same as your username or first name' + # validates_exclusion_of :karma, in: :reserved_karmas # end # # Configuration options: # * :in - An enumerable object of items that the value shouldn't - # be part of. This can be supplied as a proc or lambda which returns an + # be part of. This can be supplied as a proc, lambda or symbol which returns an # enumerable. If the enumerable is a range the test is performed with # * :within - A synonym(or alias) for :in # Range#cover?, otherwise with include?. diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb index c2835c550bcaa629099d9ba171484ca27f440fa6..babc8982daf787e26eb31ed22d1bfa5fabe79002 100644 --- a/activemodel/lib/active_model/validations/inclusion.rb +++ b/activemodel/lib/active_model/validations/inclusion.rb @@ -23,11 +23,12 @@ module HelperMethods # validates_inclusion_of :age, in: 0..99 # validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list" # validates_inclusion_of :states, in: ->(person) { STATES[person.country] } + # validates_inclusion_of :karma, in: :available_karmas # end # # Configuration options: # * :in - An enumerable object of available items. This can be - # supplied as a proc or lambda which returns an enumerable. If the + # supplied as a proc, lambda or symbol which returns an enumerable. If the # enumerable is a range the test is performed with Range#cover?, # otherwise with include?. # * :within - A synonym(or alias) for :in diff --git a/activemodel/test/cases/validations/exclusion_validation_test.rb b/activemodel/test/cases/validations/exclusion_validation_test.rb index baccf72ecb023c1248f036bbeafdb1a5267ce5b4..9f916dbfdd7d1081d9b029ff7fe94450da56189e 100644 --- a/activemodel/test/cases/validations/exclusion_validation_test.rb +++ b/activemodel/test/cases/validations/exclusion_validation_test.rb @@ -64,4 +64,26 @@ def test_validates_exclusion_of_with_lambda t.title = "wasabi" assert t.valid? end + + def test_validates_inclusion_of_with_symbol + Person.validates_exclusion_of :karma, :in => :reserved_karmas + + p = Person.new + p.karma = "abe" + + def p.reserved_karmas + %w(abe) + end + + assert p.invalid? + assert_equal ["is reserved"], p.errors[:karma] + + def p.reserved_karmas + %w() + end + + assert p.valid? + ensure + Person.reset_callbacks(:validate) + end end diff --git a/activemodel/test/cases/validations/inclusion_validation_test.rb b/activemodel/test/cases/validations/inclusion_validation_test.rb index c57fa75faf34ffadd2dd59dbb73aba48a1eaab82..92638f8e707b900e71bb962a5ca1fce79bf0575b 100644 --- a/activemodel/test/cases/validations/inclusion_validation_test.rb +++ b/activemodel/test/cases/validations/inclusion_validation_test.rb @@ -96,4 +96,26 @@ def test_validates_inclusion_of_with_lambda t.title = "elephant" assert t.valid? end + + def test_validates_inclusion_of_with_symbol + Person.validates_inclusion_of :karma, :in => :available_karmas + + p = Person.new + p.karma = "Lifo" + + def p.available_karmas + %w() + end + + assert p.invalid? + assert_equal ["is not included in the list"], p.errors[:karma] + + def p.available_karmas + %w(Lifo) + end + + assert p.valid? + ensure + Person.reset_callbacks(:validate) + end end