从其json表示中获取IPAddr实例

如何从json表示中获取IPAddr实例?

语境:

我正在使用一个使用draftsmangem的Rails应用程序。 基本上,当一个人对数据库中的记录和ruby模型has_drafts进行更改时,不会立即对记录进行更改,而是将更改草稿和结果记录保存在草稿表中,直到一次publish!为止publish! 那个草案。 然后对实际记录进行更改。 很简约 :)

草稿表保存了允许更改发生在postgres表中的json列中的对象。

我也使用Devise,我的用户模型使用trackable模块,其中包括current_sign_in_ip以及列类型inetlast_sign_in_ip

问题:

我的用户表中的inet类型列以及User对象的其余部分存储在由draftsman gem在名为object的单个json列中创建的草稿表中。 由于以下原因,在这种情况下从对象中重新定义对象不成功: IPAddr实例具有IPAddr类无法感知的json表示。 例如,ruby中的IPAddr实例响应to_json ,这给我一些如下所示的内容: "\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}" 。 这些实例也响应to_s并给我这样的东西: "127.0.0.1" 。 不幸的是, IPAddr类似乎不知道如何从我所知道的json中恢复过来:

 [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'] # (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) # (byebug) IPAddr.new(data[:object]['current_sign_in_ip'].to_json) *** IPAddr::InvalidAddressError Exception: invalid address nil (byebug) 

我想将这个问题发布到StackOverflow会引起一些关注这个问题,但是如果需要任何其他信息,我还在Draftsman github页面上提交了一个github 问题 。

不确定这是否有帮助,但如果您在d_ethier的回答下面阅读我的评论,您会发现IPAddr并不真正了解JSON。

但是你可以修补它来理解JSON,如下所示:

 require 'active_model' require 'active_support' require 'active_support/core_ext' require 'ipaddr' class IPAddr include ActiveModel::Serializers::JSON attr_accessor :addr, :mask_addr, :family def attributes=(hash) hash.each do |key, value| send("#{key}=", value) end end def attributes instance_values end end pi = IPAddr.new('127.0.0.1') pj = i.to_json p IPAddr.new.from_json(j) 

输出:

 # "{\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}" # 

资源:
http://apidock.com/rails/ActiveModel/Serializers/JSON/from_json

我怀疑这个问题是别的。

IPAddr.new(data[:object]['current_sign_in_ip'].to_s)不会改变data[:object]['current_sign_in_ip'] ,因此不应该有理由将其“转换”回来。

实际上, data[:object]['current_sign_in_ip']已经是一个IPAddr对象。 在IPAddr.new中包装它是多余的。

我怀疑你正在尝试做别的事,这只是你的描述,所以如果没有看到你的代码,就很难提供帮助。

如果是这种情况,您可以通过为原始IPAddr实例创建变量并稍后使用它来解决此问题。

 original_ipaddr = data[:object]['current_sign_in_ip'] ... rest of your code IPAddr.new(data[:object]['current_sign_in_ip'].to_json) IPAddr.new(original_ipaddr.to_s)