Not Using IPAddr Should Result In You Being Mauled By A Bear

I wrote a huge rant about stupid people storing IP addresses as a CHAR(15) in the DB. I then gave up and realized stupid people will remain stupid, and intelligent people will learn. Use an INT(4), it’s a huge saving in size and indexing will be fast.

“kris, Im not a stupid person, and want to learn, but how would you recommend doing so?”. Dear reader, I’m not Jesus (yet), but a simple google search will either lead you back to this post, or directly to IPAddr.

1
2
3
4
5
6
require 'rubygems'
require 'ipaddr'

ip = IPAddr.new('127.0.0.1')
puts "Normal: #{ip.to_s} - Converted: #{ip.to_i}"
>> Normal: 127.0.0.1 - Converted: 2130706433

What’s even cooler, is the ability to see if an ip belongs to a network.

1
2
3
network = IPAddr.new("192.168.1.0/24")
puts network.include?(IPAddr.new("192.168.1.0"))
>> true

Now, there are many more options, but my goal here is not to teach you IPAddr, but to kick your ass in the proper direction. This way, you won’t write stupid code (Stupid, being completely subjective, for now, until I’m Jesus). G’day.

No related posts.

  • After seeing this, I decided to hack together an ActiveRecord extension to let you do this automatically: http://github.com/technicalpickles/has_ip_address

    The only real issue I had IPAddr is that it's not easy to go back from an integer back into an IPAddr. I ended up using a hack that involved bitwise manipulation to get the dot notation back, and then pass that back to IPAddr.
  • What do you mean "not easy"? What issues did you run into? You should be able to simply call IPAddr.new(ipasint).to_s
  • Have you actually tried it? When I say "not easy" as in "it doesn't work". The RDoc also suggests this wouldn't work. Check out this irb session: http://pastebin.com/m60316c30

    This is the workaround I used: http://basic70tech.wordpress.com/2007/04/13/32-...
  • Followup:

    I actually bothered to look at the error, and the code that causes it in the constuctor. I realized you need to do this: IPAddr.new(ipasint, Socket::AF_INET)

    I'll probably update has_ip_address to assume it's ipv4 until I can figure out a way to make that more configurable.
  • Doh! Yeah I remember using Socket::AF_INET but removed it, forgetting to test the reversal. Apologies.
  • theRemix
    lol just heard a mention of this post on RailsEnvy podcast, funny. http://itunes.apple.com/WebObjects/MZStore.woa/...
  • This code will not work with IPv6. IPv6 addresses are 128bit so an INT(4) will not store them:

    http://en.wikipedia.org/wiki/IPv6

    >> IPAddr.new('ff06::c3').to_i.size
    => 16
  • Grouchy
    Are you seriously this fucking stupid?

    I mean, really. No shit the storage is too small for something that's never been implemented outside of classrooms and your office where you masturbate daily to covers of O'reilly books.

    Thanks for letting us know, champ. Be sure to follow up when BGPv8 comes out.
  • Agreed, but actual IPV6 usage is extremely slim and pretty much for Internet2 users, unless you're tunneling IPV6 over IPV4 tunnels.
  • The thing about being stupid is probably some sort of irony, but not being able to support IPv6 is...stupid. Microsoft kind of philosophy to ignore new standards - not very scalable.
  • IPv6 isn't a standard, nor is it widely adopted. So, your statement regarding me ignoring standards and not being scalable is silly. Is the server that hosts your website responding to IPv6 requests? Is your site 100% up to new standards?
  • It's a fact it will be, and you know that too I'm sure. It seems you assume everyone is working on regular websites, and storing info like so: no. I follow the standards I see will make big impact on Internet and humanity in the future, and everyone should do that too (unless experimenting with own stuff, because then it's just killing creativity). Just building stuff for today is not what drives me personally that's why, and if everyone did that we would have less technology development/adaption. Anyway, I think you got my point/opinion: Don't state everyone is stupid if there are more than one side of the coin.
  • By the time IPv6 is adopted, the application will more than likely be revamped, if not, a single alter table statement will will fix its size. The post wasn't necessarily aimed at saving space as much as it is was indexing speed. Either way, even storing as a CHAR(15) would still require an ALTER statement.
blog comments powered by Disqus