从其json表示中获取IPAddr实例
如何从json表示中获取IPAddr
实例?
语境:
我正在使用一个使用draftsman
gem的Rails应用程序。 基本上,当一个人对数据库中的记录和ruby模型has_drafts
进行更改时,不会立即对记录进行更改,而是将更改草稿和结果记录保存在草稿表中,直到一次publish!
为止publish!
那个草案。 然后对实际记录进行更改。 很简约 :)
草稿表保存了允许更改发生在postgres表中的json列中的对象。
我也使用Devise,我的用户模型使用trackable
模块,其中包括current_sign_in_ip
以及列类型inet
的last_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)