Does Rails 3 or Ruby have a built-in way to check if a variable is an integer?
For example,
1.is_an_int #=> true
"[email protected]".is_an_int #=> false?
Does Rails 3 or Ruby have a built-in way to check if a variable is an integer?
For example,
1.is_an_int #=> true
"[email protected]".is_an_int #=> false?
You can use the is_a? method
>> 1.is_a? Integer
=> true
>> "[email protected]".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
Integer(obj) rescue false This will not work for "1" if you want to check if it will convertIf you want to know whether an object is an Integer or something which can meaningfully be converted to an Integer (NOT including things like "hello", which to_i will convert to 0):
result = Integer(obj) rescue false
Integer(2.5) => 2 is always a meaningful conversion.Use a regular expression on a string:
def is_numeric?(obj)
obj.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
end
If you want to check if a variable is of certain type, you can simply use kind_of?:
1.kind_of? Integer #true
(1.5).kind_of? Float #true
is_numeric? "545" #true
is_numeric? "2aa" #false
\d+? the ? specifies a non-greedy match, whereas you probably want an optional match. Changing \d+? to \d* might fix it, but I'd want to run it through a suite of tests to be sure. This also won't match hex or exponential notation, but I'm sure that's fine for certain use cases.\A\d+\z?Integer(obj) rescue false code from @alex-d below; regexp is difficult to read and not clear in its intent. Both work, I came to this question in an attempt to fix a poorly constructed regexp that was not always working :-)If you're uncertain of the type of the variable (it could be a string of number characters), say it was a credit card number passed into the params, so it would originally be a string but you want to make sure it doesn't have any letter characters in it, I would use this method:
def is_number?(obj)
obj.to_s == obj.to_i.to_s
end
is_number? "123fh" # false
is_number? "12345" # true
@Benny points out an oversight of this method, keep this in mind:
is_number? "01" # false. oops!
In case you don't need to convert zero values, I find the methods to_i and to_f to be extremely useful since they will convert the string to either a zero value (if not convertible or zero) or the actual Integer or Float value.
"0014.56".to_i # => 14
"0014.56".to_f # => 14.56
"0.0".to_f # => 0.0
"not_an_int".to_f # 0
"not_a_float".to_f # 0.0
"0014.56".to_f ? "I'm a float" : "I'm not a float or the 0.0 float"
# => I'm a float
"not a float" ? "I'm a float" : "I'm not a float or the 0.0 float"
# => "I'm not a float or the 0.0 float"
EDIT2 : be careful, the 0 integer value is not falsey it's truthy (!!0 #=> true) (thanks @prettycoder)
EDIT
Ah just found out about the dark cases... seems to only happen if the number is in first position though
"12blah".to_i => 12
To capitalize on the answer of Alex D, using refinements:
module CoreExtensions
module Integerable
refine String do
def integer?
Integer(self)
rescue ArgumentError
false
else
true
end
end
end
end
Later, in you class:
require 'core_ext/string/integerable'
class MyClass
using CoreExtensions::Integerable
def method
'my_string'.integer?
end
end
I have had a similar issue before trying to determine if something is a string or any sort of number whatsoever. I have tried using a regular expression, but that is not reliable for my use case. Instead, you can check the variable's class to see if it is a descendant of the Numeric class.
if column.class < Numeric
number_to_currency(column)
else
column.html_safe
end
In this situation, you could also substitute for any of the Numeric descendants: BigDecimal, Date::Infinity, Integer, Fixnum, Float, Bignum, Rational, Complex
to_i. That's part of Ruby's "duck typing": If it can act like an integer, treat it like one.'0xdeadbeef'.to_i #=> 0but'0xdeadbeef'.to_i(16) #=> 3735928559as does'deadbeef'.to_i(16) #=> 3735928559or'deadbeef'.to_i(16).to_s(16) #=> "deadbeef". We're expected to test to make sure we're catching the corner cases but somethings things get slippery. Otherwise we can go old-school and do it asking about types and be more limiting. This is the crux of the arguments surrounding duck-typing.kind_of?is an alias tois_a?.is_a?is slightly different; it asks if the object of an instance of a specific class;kind_of?asks if it is an instance or child of a specific class.fido.is_a? Dogis true;fido.kind_of? Animalis true, for example.