Injured by Integer

Posted by Nicholas Sat, 05 Apr 2008 02:35:00 GMT

It’s been a very long time since I’ve used Kernel#Integer, but to my recollection it was simply coercion that raised an error if necessary, as an alternative to things like String#to_i which would simply return the first digits in a string, or 0 if the string did not contain a valid integer.

Since the program I was writing was receiving amounts in the form of strings representing cents, I figured it would be a natural fit. Leading zeros would be stripped off of anything under a buck, and I could simply rescue any ArgumentError and handle them appropriately.

A short while in production and I’m starting to get some bug reports that are pretty tricky to replicate.

Turns out, my memory has failed me yet again! Integer does not, in fact, do anything close to what I thought it did.

Let’s take a peek inside irb so we can take a harder look at what was causing all of my problems.

>> Integer( "085" )
ArgumentError: invalid value for Integer: "085" 
    from (irb):3:in `Integer'
    from (irb):3
>> Integer( "022" )
=> 18

Now at a glance you can probably already deduce that I was expecting to get 85 and 22 as the respective results, not an ArgumentError and 18! Keep in mind that I also had a bit of special sauce to handle ArgumentErrors, I just hadn’t planned on arriving at them through the avenue shown above.

A quick peek at the API tells me exactly why such behavior was occurring:

“If arg is a String, leading radix indicators (0, 0b, and 0x) are honored. Others are converted using to_int and to_i.”

Wow. Ok. More than a little unexpected. After having discovered the problem, the bug it caused was easily squashed. Lesson learned, programming from memory is not always a great idea. Even when the tests pass!

NOTE TO SELF: Kernel#Integer is not simply an alternative to String#to_i that raises an error.

You live, you learn. And then you get luvz.

Comments

(leave url/email »)