public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Add :tokenizer option to validates_length_of. [#507 state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
dfl (author)
Sat Jun 28 17:41:12 -0700 2008
lifo (committer)
Thu Jul 03 17:34:33 -0700 2008
commit  dd8946231c1d8a8f0ac4e299c66d87226a157a1a
tree    38929837e0988043b187e43725632d2cc70af262
parent  a78750f16d19bf988958b92fb0cdf9e575790b94
...
1
2
 
 
 
 
 
3
4
5
...
1
2
3
4
5
6
7
8
9
10
0
@@ -1,5 +1,10 @@
0
 *2.1.1 (next release)*
0
 
0
+* Add :tokenizer option to validates_length_of to specify how to split up the attribute string. #507. [David Lowenfels] Example :
0
+
0
+  # Ensure essay contains at least 100 words.
0
+  validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least %d words."), :tokenizer => lambda {|str| str.scan(/\w+/) }
0
+
0
 * Always treat integer :limit as byte length.  #420 [Tarmo Tänav]
0
 
0
 * Partial updates don't update lock_version if nothing changed.  #426 [Daniel Morrison]
...
480
481
482
483
484
 
 
 
485
486
487
...
492
493
494
495
496
497
498
...
504
505
506
 
 
 
507
508
509
510
511
512
 
 
513
514
515
...
536
537
538
539
 
540
541
542
...
553
554
555
556
 
557
558
559
...
480
481
482
 
 
483
484
485
486
487
488
...
493
494
495
 
496
497
498
...
504
505
506
507
508
509
510
511
512
513
514
 
515
516
517
518
519
...
540
541
542
 
543
544
545
546
...
557
558
559
 
560
561
562
563
0
@@ -480,8 +480,9 @@ module ActiveRecord
0
       #     validates_length_of :fax, :in => 7..32, :allow_nil => true
0
       #     validates_length_of :phone, :in => 7..32, :allow_blank => true
0
       #     validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
0
-      #     validates_length_of :fav_bra_size, :minimum=>1, :too_short=>"please enter at least %d character"
0
-      #     validates_length_of :smurf_leader, :is=>4, :message=>"papa is spelled with %d characters... don't play me."
0
+      #     validates_length_of :fav_bra_size, :minimum => 1, :too_short => "please enter at least %d character"
0
+      #     validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with %d characters... don't play me."
0
+      #     validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least %d words."), :tokenizer => lambda {|str| str.scan(/\w+/) }
0
       #   end
0
       #
0
       # Configuration options:
0
@@ -492,7 +493,6 @@ module ActiveRecord
0
       # * <tt>:in</tt> - A synonym(or alias) for <tt>:within</tt>.
0
       # * <tt>:allow_nil</tt> - Attribute may be +nil+; skip validation.
0
       # * <tt>:allow_blank</tt> - Attribute may be blank; skip validation.
0
-      #
0
       # * <tt>:too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %d characters)").
0
       # * <tt>:too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters)").
0
       # * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt> method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters)").
0
@@ -504,12 +504,16 @@ module ActiveRecord
0
       # * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
0
       #   not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>).  The
0
       #   method, proc or string should return or evaluate to a true or false value.
0
+      # * <tt>:tokenizer</tt> - Specifies how to split up the attribute string. (e.g. <tt>:tokenizer => lambda {|str| str.scan(/\w+/)}</tt> to
0
+      #   count words as in above example.)
0
+      #   Defaults to <tt>lambda{ |value| value.split(//) }</tt> which counts individual characters.
0
       def validates_length_of(*attrs)
0
         # Merge given options with defaults.
0
         options = {
0
           :too_long     => ActiveRecord::Errors.default_error_messages[:too_long],
0
           :too_short    => ActiveRecord::Errors.default_error_messages[:too_short],
0
-          :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length]
0
+          :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length],
0
+          :tokenizer    => lambda {|value| value.split(//)}
0
         }.merge(DEFAULT_VALIDATION_OPTIONS)
0
         options.update(attrs.extract_options!.symbolize_keys)
0
 
0
@@ -536,7 +540,7 @@ module ActiveRecord
0
             too_long  = options[:too_long]  % option_value.end
0
 
0
             validates_each(attrs, options) do |record, attr, value|
0
-              value = value.split(//) if value.kind_of?(String)
0
+              value = options[:tokenizer].call(value) if value.kind_of?(String)
0
               if value.nil? or value.size < option_value.begin
0
                 record.errors.add(attr, too_short)
0
               elsif value.size > option_value.end
0
@@ -553,7 +557,7 @@ module ActiveRecord
0
             message = (options[:message] || options[message_options[option]]) % option_value
0
 
0
             validates_each(attrs, options) do |record, attr, value|
0
-              value = value.split(//) if value.kind_of?(String)
0
+              value = options[:tokenizer].call(value) if value.kind_of?(String)
0
               record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value]
0
             end
0
         end
...
1059
1060
1061
 
 
 
 
 
 
 
 
 
 
 
 
1062
1063
1064
...
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
0
@@ -1059,6 +1059,18 @@ class ValidationsTest < ActiveRecord::TestCase
0
     end
0
   end
0
 
0
+  def test_validates_length_of_with_block
0
+    Topic.validates_length_of :content, :minimum => 5, :too_short=>"Your essay must be at least %d words.", 
0
+                                        :tokenizer => lambda {|str| str.scan(/\w+/) }
0
+    t = Topic.create!(:content => "this content should be long enough")
0
+    assert t.valid?
0
+
0
+    t.content = "not long enough"
0
+    assert !t.valid?
0
+    assert t.errors.on(:content)
0
+    assert_equal "Your essay must be at least 5 words.", t.errors[:content]
0
+  end
0
+
0
   def test_validates_size_of_association_utf8
0
     with_kcode('UTF8') do
0
       assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }

Comments