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.