How can I get back an IPAddr
instance from its json representation?
Context:
I'm working on a Rails application that uses the draftsman
gem. Essentially, when one makes a change to a record in the database and that ruby model has_drafts
, instead of making the change to the record right away, a draft of the changes and the resulting record is saved in the drafts table until one publish!
es that draft. Then the changes are made to the actual record. Pretty neat :)
The drafts table holds the object that would result from allowing the changes to happen in a json column in a postgres table.
I'm also using Devise and my user model uses the trackable
module, which includes a current_sign_in_ip
as well as a last_sign_in_ip
of column type inet
.
Problem:
inet
type columns in my user table, as well as the rest of the User
object, are being stored in the drafts table created by the draftsman
gem in a single json column called object
. reify
ing the object from its draft does not succeed in this case because of the following reason: IPAddr
instances have a json representation that the IPAddr
class is incapable of perceiving. For example, IPAddr
instances in ruby respond to to_json
, which gives me something that looks like this: "\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
. These instances also respond to to_s
and give me something like this: "127.0.0.1"
. Unfortunately, the IPAddr
class doesn't seem to know how to bring itself back from json from what I can tell:
[277, 286] in /home/jake/.rvm/gems/ruby-2.2.1/bundler/gems/draftsman-1bd3c797d540/lib/draftsman/model.rb
277: data = {
278: :item => self,
279: :whodunnit => Draftsman.whodunnit,
280: :object => object_attrs_for_draft_record
281: }
=> 282: data = merge_metadata_for_draft(data)
283:
284: # If there's already a draft, update it.
285: if send(self.class.draft_association_name).present?
286: data[:object_changes] = changes_for_draftsman if track_object_changes_for_draft?
(byebug) data[:object]['current_sign_in_ip']
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
(byebug) data[:object]['current_sign_in_ip'].to_json
"{\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
(byebug) IPAddr.new(data[:object]['current_sign_in_ip'].to_s)
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
(byebug) IPAddr.new(data[:object]['current_sign_in_ip'].to_json)
*** IPAddr::InvalidAddressError Exception: invalid address
nil
(byebug)
I figured posting this question to StackOverflow would get some attention to this issue, but I also submitted a github issue on the Draftsman
github page if any other information is needed.