Avoid Rails converting PostgreSQL inet type to an IPAddr object?
Asked Answered
C

1

6

I have a problem in my Rails project. In previous projects (not Rails) I just used the "inet" type in PostgreSQL to store an IP address with a subnet, something like this:

 192.168.1.0/30 
 192.168.1.1/30
 192.168.1.2/30
 192.168.1.3/30

This was a good method to store the IP and the subnet in one field. Now I am using the inet type in Rails (4.0.1) and Ruby (2.0.0 p247), but as I read and tried, Rails converts it to the IPAddr object. But this IPAddr Object is destroying my format. It converts the four examples above to the following:

 192.168.1.0/30

Is there a way to prevent Rails doing that or is there a way to substitute it with a string? Or maybe another gem?

The problem occurs when I try to store something, and even when I try to read an existing value from the database.

Just to be more granular:

 IPAddr.new("192.168.1.2/255.255.255.252") 

Creates the database entry:

 192.168.1.0/24
Confounded answered 31/3, 2014 at 21:24 Comment(0)
P
4

If I remember right, 192.168.1.0/30 is technically correct.

Here's a couple things that might help:

  • In addition to IPAddr, a very good gem for working with IPv4 and IPv6 is IPAddress. It won't help much if Active Record has passed the value to IPAddr already, and it has changed the value, so you'll need to tell Active Record to use IPAddress instead.
  • Storing your addresses as PostgreSQL "inet" type is fine, if you intend to use PostgreSQL to handle your subnetting needs via its built-in IP functions. It's a bad idea if you want to simply store the IP address and retrieve it, as you found out. Active Record tries to honor the field type, and map it to the closest Ruby class, which is IPAddr. Instead, I always store my IPs both as a string, for fast retrieval in the form I want, and as a suitably sized integer, so I can do all my subnetting manipulations and matches in binary.

    It might help if, in your query, you tell PostgreSQL to cast your value to a string before returning it to Active Record. At that point you could use IPAddress to work with the value after parsing it. How to tell Active Record to tell PostgreSQL to do that is a different question.

Phial answered 31/3, 2014 at 22:39 Comment(2)
Thank you, I tried now something with composed_of, to convert it automatically to an IPAddress object, but it is not working correctly.Confounded
Just curious how you tell active record to use IPAddressSfax

© 2022 - 2024 — McMap. All rights reserved.