How to cleanly verify if the user input is an integer in Ruby?
This will do to validate the input:
Integer(gets) rescue nil
How do I check if user input is an integer in Ruby?
The main issue with your code is String#to_i
method is omnivorous.
"0".to_i #⇒ 0
"0.1".to_i #⇒ 0
"foo".to_i #⇒ 0
That said, user_input
in your code is always integer.
What you probably want is to accept digits only (and maybe a leading minus for negatives.) The only concise way to accept a subset of characters is a regular expression.
# chomp to strip out trailing carriage return
user_input = gets.chomp
if user_input =~ /\A-?\d+\z/
...
The regular expression above means nothing save for digits with optional leading minus.
Or, even better (credits to @Stefan)
if gets =~ /\A-?\d+\Z/
Checking if input == Integer/float? using irb
There's a much more Ruby way to express this, the idiomatic form if you will:
loop do
puts "What type of soaps do you want? (1 = face soap, 2 = bar soap, 3 = shave soap, 4 = shampoo soap) Please put a number from 1 - 4 "
case (soap = gets)
when '1'
puts "Great! You want face soap."
when '2'
puts "Great! You want bar soap"
when '3'
puts "Great! You want shave soap."
when '4'
puts "Great! You want shampoo soap."
else
puts "#{soap.inspect} is not a valid entry, please try again."
end
end
Where the case
statement can do a ton of work for you. Here the string values are being tested instead of bothering to convert since that doesn't really matter.
Notice there's still a lot of duplication though. This is where a look-up table can be the key to simplifying things:
SOAPS = {
1 => 'face soap',
2 => 'bar soap',
3 => 'shave soap',
4 => 'shampoo soap'
}.freeze
loop do
puts "What type of soaps do you want? (#{SOAPS.map { |k, v| "#{k} - #{v}" }.join(', ')}) Please put a number from 1 - 4 "
soap = gets
if (soap_type = SOAPS[soap.to_i])
puts "Great! You want #{soap_type}."
else
puts "#{soap.inspect} is not a valid entry, please try again."
end
end
Where now you can easily add and remove entires and everything updates accordingly. This is a data-driven approach and it's what Ruby excels at because once you have something expressed in terms of data, you can build on that with a series of transformations to get the desired result.
Checking if a variable is an integer
You can use the is_a?
method
>> 1.is_a? Integer
=> true
>> "dadadad@asdasd.net".is_a? Integer
=> false
>> nil.is_a? Integer
=> false
How to test if a string is basically an integer in quotes using Ruby
You can use regular expressions. Here is the function with @janm's suggestions.
class String
def is_i?
!!(self =~ /\A[-+]?[0-9]+\z/)
end
end
An edited version according to comment from @wich:
class String
def is_i?
/\A[-+]?\d+\z/ === self
end
end
In case you only need to check positive numbers
if !/\A\d+\z/.match(string_to_check)
#Is not a positive number
else
#Is all good ..continue
end
Accept only numeric input
Try regular expressions, like this:
puts "Enter numeric value: "
result = gets
if result =~ /^-?[0-9]+$/
puts "Valid input"
else
puts "Invalid input."
end
The example above allows only digits [0..9].
If you want to read not only integers, you can allow a dot as well: ^-?[0-9]+$/
. Read more about regexp in Ruby: http://ruby-doc.org/core-2.2.0/Regexp.html
Test if the number input is not a text - RUBY
There's several things to note here. For one, the result of to_i
is always an Integer type value. Testing that !a.is_a? Integer
is redundant as that will never fail.
You'll also need to remember that the case
statement itself makes it very easy to compare to classes:
case (a)
when Integer
puts "I'm a number!"
when String
puts "I'm a string!"
end
Note that the first condition is automatically triggered for any Integer values.
There's limits on what you can put in a when
clause even if they are fairly generous. To get the parser to properly interpret what you're asking for, you'd have to express it like this:
when !a.is_a?(Integer)
Though as noted this can be reduced down to when Integer
so the rest of that is redundant.
You'll also want to avoid specifying something in the case
part, and then later referring to a variable. It's confusing to anyone reading your code and probably unnecessary. If you're dealing with complicated logic, use a series of if
statements to make things clear.
Related Topics
How to Use Mongodb Ruby Driver to Do a "Group" (Group By)
Ruby Google_Drive Gem Oauth2 Saving
HTML Is Read Before Fully Loaded Using Open-Uri and Nokogiri
Why Require Mongo Gives Me Loaderror: No Such File to Load -- Openssl
Nokogiri Requires Ruby Version < 2.3
Passing Params to Cancan in Ror
How to Convert a Nested Hash into Xml Using Nokogiri
How to Understand Sender and Receiver in Ruby
Use Rspec's "Expect" etc. Outside a Describe ... It Block
Multiple Servers in a Single Eventmachine Reactor
Rails 3 Actionmail Openssl::Ssl::Sslerror
Best Practices in Ruby for Loop
Graphql::Client::Dynamicqueryerror Expected Definition to Be Assigned to a Static Constant
Creating a Test Suite Using Ruby Minitest
Converting an Array of Hashes to One Hash in Ruby
Rails: How to to Download a File from a Http and Save It into Database