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
If I remember right, 192.168.1.0/30
is technically correct.
Here's a couple things that might help:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With