1

I'm dynamically creating attr_readers and instance variables based on a response_header received from an API.

The response_header hash comes back like this:

{
    "server"=>"nginx",
    "x-ua-compatible"=>"IE=edge,chrome=1",
    "expires"=>"Thu, 01 Jan 1970 00:00:00 GMT",
    "cache-control"=>"no-cache, must-revalidate",
    "pragma"=>"no-cache",
    "rate-limit"=>"1000",
    "rate-limit-remaining"=>"986",
    "rate-limit-reset"=>"1265",
    "content-type"=>"application/json;charset=UTF-8",
    "content-language"=>"en",
    "transfer-encoding"=>"chunked",
    "vary"=>"Accept-Encoding",
    "date"=>"Fri, 23 Jan 2015 15:38:56 GMT",
    "connection"=>"close",
    "x-frame-options"=>"SAMEORIGIN"
  }

This get's sent into a class called ResponseHeader

  class ResponseHeader
    def initialize(options = {})
      options.each do |key, value|
        instance_variable_set("@#{key}", value)
        self.send(:attr_reader, key)
      end
    end
  end

This is working pretty well except for the fact that rate-limit, rate-limit-remaining and rate-limit-reset are clearly integers that came back as strings from the API.

I'd like for my class to be intelligent here and change those values to integers but the only method I've come up with thus far feels very un-ruby.

Basically I'm converting to an integer and then back to a string and seeing if it equals the original value.

[8] pry(main)> "ABC".to_i
=> 0
[9] pry(main)> _.to_s
=> "0"
[10] pry(main)> _ == "ABC"
=> false
[11] pry(main)> "100".to_i
=> 100
[12] pry(main)> _.to_s
=> "100"
[13] pry(main)> _ == "100"
=> true

Is this my only option?

Anthony
  • 15,435
  • 4
  • 39
  • 69
  • possible duplicate of [Test if a string is basically an integer in quotes using Ruby?](http://stackoverflow.com/questions/1235863/test-if-a-string-is-basically-an-integer-in-quotes-using-ruby) – Rustam Gasanov Jan 23 '15 at 16:38

1 Answers1

2

Ruby Integer parses a string to an integer and raises an error if the parse fails:

i = Integer("123")  #=> 1234
i = Integer("abc")  #=> ArgumentError: invalid value for Integer(): "abc"

Heads up that binary, octal, and hex are also parsed:

i = Integer("0b10")  #=> 2
i = Integer("010")   #=> 8
i = Integer("0x10")  #=> 16

To parse base 10, provide the base:

i = Integer("010",10)  #=> 10

To match within a string, use a regexp:

s = "foo123bar"
i = s=~/-?\d+/ ? Integer($&,10) : nil  #=> 123

To patch the String class, define a new method:

class String
  def match_integer
    self=~/-?\d+/ ? Integer($&,10) : nil
  end
end

"foo123bar".match_integer  #=> 123
joelparkerhenderson
  • 34,808
  • 19
  • 98
  • 119