views:

408

answers:

6

I wanted to validate 'numericality' of a string (its not an attribute in an active-record model). I just need it to be a valid base 10, positive integer string. I am doing this:

class String
   def numeric?
      # Check if every character is a digit
      !!self.match(/\A[0-9]+\Z/)
   end
end

class String
   def numeric?
      # Check is there is *any* non-numeric character
      !self.match(/[^0-9]/)
   end
end

Which of these is a more plausible alternative? OR, is there any other better implementation?

+3  A: 

The first one looks sane to me.

I'd name the method numeric?, though. I'm not a big fan of is_foo? methods. They make sense in languages that doesn't have question marks in method names (is_foo, isFoo), but with the question mark, the is feels redundant.

August Lilleaas
I ended up using the second one.
Swanand
+1  A: 

The second will finish quicker in the case of a non-numeric string, as it will reject on the first bad character.

Also, check out the String#to_i method - it possibly does what you want:
http://www.ruby-doc.org/core/classes/String.html#M000787

zaius
the problem with to_i is you never know if it is 0 or not a number.
moogs
Exactly why I didn't use it.
Swanand
+1  A: 

I dont know if this is fast, but I like:

class String
 def numeric?
    true if Integer(object) rescue false
 end
end

Handles negative numbers as well. And if you ever wanted to support floats in the future, just use Float()

moogs
aw crap, using this would make "0x122" numeric. oh well..
moogs
+2  A: 

I'm not a 100% certain but Rails seems to be using /\A[+-]?\d+\Z/ for integers.
Click on show source for validates_numericality_of here

Gishu
\A -> Start of string\Z -> End of stringBasically the same I am unsing in First one, except the positive/negative modifier part.
Swanand
+3  A: 

Please make sure use \A and \Z rather than ^ and $, to match the entire string rather than just a single line in the string. If you want to avoid matching a string with an ending newline, use '\z' at the end. For more issues, see The Regex Tutorial on anchors.

For example, /^[0-9]+$/ successfully matches the following:

foo
1234
bar

but /\A[0-9]+\Z/ does not.

Bkkbrad
A: 

According to a simple benchmark, the second approach is faster, although I'm not expert benchmarker, so this might not be a valid benchmark: http://pastie.org/586777

Zalus' logic is right. It only needs to check once for a non-valid string.

Lonecat