Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #10019 (closed defect: fixed)

Opened 10 months ago

Last modified 5 months ago

validates_length_of fails on pure number values when using :within/:in

Reported by: bwalton Assigned to: core
Priority: normal Milestone: 1.2.7
Component: ActiveRecord Version: edge
Severity: normal Keywords: validations
Cc:

Description

validates_length_of using :within doesn't account for objects that don't handle .split. If the value of the object is a FixNum (for example) the error generated during validation is:

NoMethodError: private method `split' called for 1:Fixnum <backtrace>

The code that is failing from api.rubyonrails.org

466:         case option
467:           when :within, :in
468:             raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
469: 
470:             too_short = options[:too_short] % option_value.begin
471:             too_long  = options[:too_long]  % option_value.end
472: 
473:             validates_each(attrs, options) do |record, attr, value|
474:               if value.nil? or value.split(//).size < option_value.begin
475:                 record.errors.add(attr, too_short)
476:               elsif value.split(//).size > option_value.end
477:                 record.errors.add(attr, too_long)
478:               end
479:             end
480:           when :is, :minimum, :maximum

It seems that this chunk of code assumes that it's working with an object that has .respond_to?(:split) == true. If the value doesn't respond to split, the exception is triggered.

* Line 474 should be:

if value.nil? or value.to_s.length < option_value.begin

* and Line 476 should be:

elsif value.to_s.length > option_value.end

This makes a similar assumption that the object passed has a to_s method, but that should be safer than betting on split...using length instead of split(//).size should also be a little cleaner.

Another option would be to test for kind_of?(:String) as the code that handles :minimum, :maximum and :is already does...there are other ways to handle this as well.

This happens on activerecord 1.15.5.7919.

Attachments

validates_length_of_using_non_string_values_and_range_parameter.diff (2.8 kB) - added by bwalton on 10/29/07 20:39:17.
fixed my .diff, as i had inadvertently deleted a line I shouldn't have. This diff should correct the bug described.

Change History

10/29/07 20:39:17 changed by bwalton

  • attachment validates_length_of_using_non_string_values_and_range_parameter.diff added.

fixed my .diff, as i had inadvertently deleted a line I shouldn't have. This diff should correct the bug described.

11/10/07 21:28:16 changed by danger

thanks for making the patch bwalton!

I'm thinking this may be too much of a non-standard case to put it into core. Can you think of any real-world scenarios where you'd need to pass a non-string to something that's validated by length?

11/11/07 01:36:27 changed by bwalton

I just triggered it when writing test cases. I wasn't working with data from the web, which would presumably be .to_s'd before hitting the activerecord portion of things. (This is my first use of Rails and in my app, I'll be splitting activerecord from the rest of the web stack and connecting them via a custom protocol [I don't want the db directly exposed to the web]...so my guess that things are .to_s'd is only that, a guess). To me the issue isn't if, but when. The method shouldn't fall over when handed data that it doesn't expect.

If you don't feel it should be in core, that's ok, although my opinion is that it is a useful check. I've written a before validation hook for any :string fields that ensures that validate_length will get a string to work with, so my app will be ok either way in the end.

Thanks for the feedback regardless! I'm definitely enjoying Rails (although I've been a rubyist for a while now for non-web tasks).

Keep up the good work! -Ben

02/07/08 12:45:26 changed by s_tokumine

I second bwalton. I think it is unexpected functionality to have a core validation method blow up. I mean blow up, not return an error code or exception or whatnot.

The main real world place where this would occur is in testing. As testing is one of the core things a "good" Rails dev should do, I'd say this is real world enough.

S

03/11/08 08:33:27 changed by cavalle

I think this patch #11295 also solves this ticket

03/29/08 17:53:48 changed by david

  • status changed from new to closed.
  • resolution set to fixed.

(In [9129]) Fixed that validates_size_of :within works in associations (closes #11295, #10019) [cavalle]