Home > other >  Raise ArgumentError When Argument is a Hexadecimal Representation
Raise ArgumentError When Argument is a Hexadecimal Representation

Time:08-29

My script needs to accept only 'plain' integers, and raise an argument error in any other cases (letters, special symbols, floats, multiple arguments). Unfortunately, when the passed arguments is a representation for a hexadecimal like 0b1111 the script interprets it as an integer and accepts it.

Here is my script:

begin
  price = Integer ARGV[0]
rescue
  raise ArgumentError "the entered value has to be an integer"
end

if ARGV.length > 1
    raise ArgumentError, "wrong number of arguments (given #{ARGV.length}, expected 1)"
end

if price < 8
    raise ArgumentError, "the entered value has to be at least 8"
end    

if price.match?(/[A-Za-z]/)
    raise ArgumentError "the entered value has to be an integer"
end

Basically the solution I'm trying is the last block:

if price.match?(/[A-Za-z]/)
        raise ArgumentError "the entered value has to be an integer"
    end

This gives me an error: undefined method `match?' for 2:Integer (NoMethodError)

If I understand correctly match? only works with strings, but because of the first block the variable price is converted to an integer.

How could I fix my code and would price.match?(/[A-Za-z]/) even solve my problem or do I need a completely different approach?

The desired result:

Input: 0b1111

output: ArgumentError "the entered value has to be an integer

CodePudding user response:

You can use exception: false key for Integer method

Integer(nil, exception: false)
# => nil

Integer("blablabla", exception: false)
# => nil

Integer("9.3", exception: false)
# => nil

Integer("9", exception: false)
# => 9

There is also base (second) arg in this method

Integer("0b1111", exception: false)
# => 15

Integer("0b1111", 10, exception: false)
# => nil

Integer("9.3", 10, exception: false)
# => nil

Integer("9", 10, exception: false)
# => 9

Finally you can use it such way

price = Integer(ARGV[0], 10, exception: false)
raise ArgumentError("the entered value has to be an integer") if price.nil?

CodePudding user response:

After this line

price = Integer(ARGV[0])

the input is already transformed into an integer if a transformation is possible as defined in the example in the documentation of Kernel#Integer.

If you want to ensure only strings that contain pure integer values are transformed then you will need to check the format of the input string first. For example, with a Regexp like this

ARGV[0].match?(/\A\d \z/)

that returns true when the input only contains digits.

Just replace the first block in your script with

unless ARGV[0].match?(/\A\d \z/)
  raise ArgumentError "the entered value has to be an integer"
end

price = Integer(ARGV[0])

# ...

To simplify testing the preconditions I would change it to

unless ARGV&.size != 1
  raise ArgumentError, "wrong number of arguments (given #{ARGV&.size || 0}, expected 1)"
end

unless ARGV[0].match?(/\A\d \z/)
  raise ArgumentError "the entered value has to be an integer with at least 8 digits"
end

price = Integer(ARGV[0])

if price < 8
  raise ArgumentError, "the entered value has to be at least 8"
end    
  •  Tags:  
  • ruby
  • Related