# Custom validations in rails: validates\_number\_range

**URL:** <https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653>\
**Category:** Rails\
**Created:** [June 24, 2007, 8:59pm UTC](https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653 "2007-06-24T20:59:45Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ye\_Dingding](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/49beb7/32.png) [@Ye\_Dingding](https://www.ruby-forum.com/u/Ye_Dingding)\
**Post date:** [June 24, 2007, 8:59pm UTC](https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653/1 "2007-06-24T20:59:45Z")

</div>

[http://sishen.lifegoo.com/?p=42](http://sishen.lifegoo.com/?p=42)

I don’t know whether there exists a builtin validation that can check  
the  
number range. I think the requirement is normal, but indeed, i can’t  
find  
it. So i wrote a custome validation: validates\_number\_range, whose  
prototype is validates\_length\_of. If there already exists one, pls tell  
me,  
🙂

The code is below, welcome to give me any advice on my blog. And also,  
more  
details information on the blog, 🙂

module ActiveRecord  
module Validations  
module ClassMethods  
def validates\_number\_range(\*attrs)  
validates\_numericality\_of attrs.first  
options = {  
:too\_big =\> “is too big (maximum is %d)”,  
:too\_small =\> “is too small (minimum is %d)”,  
:wrong\_number =\> “is the wrong number (should be %d)”  
}.merge(DEFAULT\_VALIDATION\_OPTIONS)  
options.update(attrs.pop.symbolize\_keys) if  
attrs.last.is\_a?(Hash)

```
    # Ensure that one and only one range option is specified.
    range_options = ALL_RANGE_OPTIONS & options.keys
    case range_options.size
      when 0
        raise ArgumentError, 'Range unspecified. Specify the 

```

:within,  
:maximum, :minimum, or :is option.’  
when 1  
# Valid number of options; do nothing.  
else  
raise ArgumentError, ‘Too many range options specified.  
Choose  
only one.’  
end

```
    # Get range option and value.
    option = range_options.first
    option_value = options[range_options.first]

    case option
    when :within, :in
      raise ArgumentError, ":#{option} must be a Range" unless

```

option\_value.is\_a?(Range)

```
      too_small = options[:too_small] % option_value.begin
      too_big = options[:too_big] % option_value.end

      validates_each(attrs, options) do |record, attr, value|
        if value.nil? or value < option_value.begin
          record.errors.add(attr, too_small)
        elsif value > option_value.end
          record.errors.add(attr, too_big)
        end
      end
    when :is, :minimum, :maximum
      raise ArgumentError, ":#{option} must be a nonnegative 

```

Integer"  
unless option\_value.is\_a?(Integer) and option\_value \>= 0

```
      # Declare different validations per option.
      validity_checks = { :is => "==", :minimum => ">=", :maximum =>

```

“\<=” }  
message\_options = { :is =\> :wrong\_number, :minimum =\>  
:too\_small,  
:maximum =\> :too\_big }

```
      message = (options[:message] || 

```

options[message\_options[option]])  
% option\_value

```
      validates_each(attrs, options) do |record, attr, value|
        record.errors.add(attr, message) unless !value.nil? and

```

value.method(validity\_checks[option])[option\_value]  
end  
end  
end  
end  
end  
end

---

<div class="post-metadata">

**Author:** ![Ye\_Dingding](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/49beb7/32.png) [@Ye\_Dingding](https://www.ruby-forum.com/u/Ye_Dingding)\
**Post date:** [June 24, 2007, 9:33pm UTC](https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653/2 "2007-06-24T21:33:41Z")

</div>

If I understood what you are trying to do correctly  
validates\_length\_of :user\_name, :within =\> 6…20, :too\_long =\> “pick a  
shorter name”, :too\_short =\> “pick a longer name”

from  
[http://railsmanual.com/module/ActiveRecord::Validations::ClassMethods/validates\_length\_of/1.1.2](http://railsmanual.com/module/ActiveRecord::Validations::ClassMethods/validates_length_of/1.1.2)

Matt

Ye Dingding wrote:

> [LifeGoo.com is for sale | HugeDomains](http://sishen.lifegoo.com/?p=42)
> 
> I don’t know whether there exists a builtin validation that can check  
> the  
> number range. I think the requirement is normal, but indeed, i can’t  
> find  
> it. So i wrote a custome validation: validates\_number\_range, whose  
> prototype is validates\_length\_of. If there already exists one, pls tell  
> me,  
> 🙂

---

<div class="post-metadata">

**Author:** ![Ye\_Dingding](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/49beb7/32.png) [@Ye\_Dingding](https://www.ruby-forum.com/u/Ye_Dingding)\
**Post date:** [June 24, 2007, 10:13pm UTC](https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653/3 "2007-06-24T22:13:54Z")

</div>

No, that’s not i want to do. Sorry, my  
blog([LifeGoo.com is for sale | HugeDomains](http://sishen.lifegoo.com/?p=42))  
gives more information, so i gave less information in the mail.

My scenario is that I want to check the uploaded file size, for example,  
less than 5M. But what validates\_length\_of is the size, when is a  
fixnum, is  
4. So validates\_length\_of can’t be work for me.

Using validates\_number\_range, now i can code as below:

validates\_number\_range :file\_size,  
:maximum =\> 5242880,  
:message =\> “you can only upload file less than  
5M”,  
:on =\> :create

---

<div class="post-metadata">

**Author:** ![Ye\_Dingding](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/y/49beb7/32.png) [@Ye\_Dingding](https://www.ruby-forum.com/u/Ye_Dingding)\
**Post date:** [June 27, 2007, 11:36am UTC](https://www.ruby-forum.com/t/custom-validations-in-rails-validates-number-range/107653/4 "2007-06-27T11:36:38Z")

</div>

Today i looked through the validations.rb in rails edge. I’m glad to  
find  
that validates\_numericality\_of method already has the support for range  
check.

The related options are

- greater\_than
- greater\_than\_or\_equal\_to
- equal\_to
- less\_than
- less\_than\_or\_equal\_to
- odd
- even

With these, life are more better, 🙂
