1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #16381 from kakipo/validate-length-tokenizer

Allow symbol as values for `tokenizer` of `LengthValidator`
This commit is contained in:
Rafael Mendonça França 2015-02-13 12:09:36 -02:00
commit 7919c29d50
4 changed files with 32 additions and 7 deletions

View file

@ -1,3 +1,7 @@
* Allow symbol as values for `tokenize` of `LengthValidator`
*Kensuke Naito*
* Assigning an unknown attribute key to an `ActiveModel` instance during initialization
will now raise `ActiveModel::AttributeAssignment::UnknownAttributeError` instead of
`NoMethodError`

View file

@ -38,7 +38,7 @@ module ActiveModel
end
def validate_each(record, attribute, value)
value = tokenize(value)
value = tokenize(record, value)
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
errors_options = options.except(*RESERVED_OPTIONS)
@ -59,10 +59,14 @@ module ActiveModel
end
private
def tokenize(value)
if options[:tokenizer] && value.kind_of?(String)
options[:tokenizer].call(value)
def tokenize(record, value)
tokenizer = options[:tokenizer]
if tokenizer && value.kind_of?(String)
if tokenizer.kind_of?(Proc)
tokenizer.call(value)
elsif record.respond_to?(tokenizer)
record.send(tokenizer, value)
end
end || value
end
@ -108,8 +112,8 @@ module ActiveModel
# * <tt>:message</tt> - The error message to use for a <tt>:minimum</tt>,
# <tt>:maximum</tt>, or <tt>:is</tt> violation. An alias of the appropriate
# <tt>too_long</tt>/<tt>too_short</tt>/<tt>wrong_length</tt> message.
# * <tt>:tokenizer</tt> - Specifies how to split up the attribute string.
# (e.g. <tt>tokenizer: ->(str) { str.scan(/\w+/) }</tt> to count words
# * <tt>:tokenizer</tt> - Specifies a method, proc or string to how to split up the attribute string.
# (e.g. <tt>tokenizer: ->(str) { str.scan(/\w+/) }</tt> or <tt>tokenizer: :word_tokenizer</tt> to count words
# as in above example). Defaults to <tt>->(value) { value.split(//) }</tt>
# which counts individual characters.
#

View file

@ -330,6 +330,19 @@ class LengthValidationTest < ActiveModel::TestCase
assert_equal ["Your essay must be at least 5 words."], t.errors[:content]
end
def test_validates_length_of_with_symbol
Topic.validates_length_of :content, minimum: 5, too_short: "Your essay must be at least %{count} words.",
tokenizer: :my_word_tokenizer
t = Topic.new(content: "this content should be long enough")
assert t.valid?
t.content = "not long enough"
assert t.invalid?
assert t.errors[:content].any?
assert_equal ["Your essay must be at least 5 words."], t.errors[:content]
end
def test_validates_length_of_for_fixnum
Topic.validates_length_of(:approved, is: 4)

View file

@ -37,4 +37,8 @@ class Topic
errors.add attr, "is missing" unless send(attr)
end
def my_word_tokenizer(str)
str.scan(/\w+/)
end
end