A month or two ago, I’d noticed some RSpec tests were taking a long time to run. When my ADSL connection dropped out during the day, I found the tests took an increasingly long time to run. Strange – how can lack of Internet connectivity cause some straightforward specs to… aah, it’s because they’re doing DNS lookups all the time.
Brian Candler, a colleague of mine, then published the API-compatible (UPDATE: Brian reminds me it is mostly API-compatible – see his comment) ruby-ip. To quote verbatim:
Why not IPAddr?
Ruby bundles an IPAddr class (ipaddr.rb). However there are a number of serious problems with this library.
- Given an IP address with a netmask or prefix (e.g. 192.0.2.0/24) it’s very hard to get access to the netmask part. It involves digging around instance variables.
- It’s impossible to deal with an off-base address with prefix, because IPAddr forcibly masks it to the base. e.g. 192.0.2.53/24 is stored as 192.0.2.0/24
- IPAddr uses calls to the socket library to validate IP addresses, and this can trigger spurious DNS lookups when given an invalid IP address. ruby-ip does not depend on the socket library at all, unless you require ‘ip/socket’ to have access to the Socket::AF_INET and Socket::AF_INET6 constants.
Today’s checkin waves goodbye to IPAddr, and gives a warm handshake to IP. Thanks, Brian!
Thanks Peter. I must point out that ruby-ip is *not* API-compatible with IPAddr, but it’s mostly similar.
IPAddr.new(“1.2.3.4″) –> IP.new(“1.2.3.4″)
IPAddr.new(16909060, Socket::AF_INET) –> IP::V4.new(16909060)
There are important semantic differences when dealing with prefixes though.
IPAddr.new(“1.2.3.4/24″).to_s #=> “1.2.3.0″
IP.new(“1.2.3.4/24″).to_s #=> “1.2.3.4/24″
Google has a really good python ipaddr manipulation library for routes and networks, IPv4, IPv6, masks, etc… could you leverage that? or port it to Ruby? maybe a wrapper for it in Ruby?