从其json表示中获取IPAddr实例 [英] Get IPAddr instance from its json representation
问题描述
$ p
上下文:
我正在使用使用 draftsman
gem的Rails应用程序。基本上,当对数据库中的记录进行更改时,并且红宝石模型 has_drafts
,而不是立即更改记录,更改草案和生成的记录保存在草稿表中,直到一个发布!
。然后对实际记录进行更改。相当整齐:)
草稿表包含允许在postgres表中的json列中进行更改的对象。
我也在使用Devise,我的用户模型使用可追踪
模块,其中包含一个 current_sign_in_ip
以及列类型 inet
的 last_sign_in_ip
。
问题:
inet
在我的用户表中键入列,以及其余的用户
对象,正在存储在由 draftsman
gem创建的草稿表中,单个json列中名为物体
。在这种情况下,由于以下原因: reify
该对象不成功,因为以下原因: IPAddr
实例有一个json表示 IPAddr
类不能察觉。例如,ruby中的 IPAddr
实例响应 to_json
,这给我看起来像这样: \ family\ :2,\ addr\ :2130706433,\ mask_addr\ :4294967295}
。这些实例也响应 to_s
,并给我这样的东西:127.0.0.1
。不幸的是, IPAddr
类似乎不知道如何把自己从json从我可以告诉的东西:
< pre class =lang-rb prettyprint-override>
[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:#如果已经有草稿,请更新。
285:if send(self.class.draft_association_name).present?
286:data [:object_changes] = changes_for_draftsman如果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异常:无效地址
nil
(byebug)
我想把这个问题发布给StackOverflow会引起这个问题的一些注意,我还在 Draftsman $ c上提交了一个github 问题 $ c> 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
定义属性
instance_values
end
end
pi = IPAddr.new('127.0.0.1')
pj = i.to_json
p IPAddr.new.from_json(j)
输出:
#< IPAddr: IPv4的:127.0.0.1/255.255.255.255>
{\family\:2,\addr\:2130706433,\mask_addr\:4294967295}
#< IPAddr:IPv4:127.0。 0.1 / 255.255.255.255>
资料来源:
http://apidock.com/rails/ActiveModel/Serializers/JSON/from_json
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.
Not sure if this helps, but if you read my comment below d_ethier's answer you can see that IPAddr
doesn't really know anything about JSON.
However you can monkey patch it to understand JSON like so:
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
p i = IPAddr.new('127.0.0.1')
p j = i.to_json
p IPAddr.new.from_json(j)
Output:
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
"{\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
Source:
http://apidock.com/rails/ActiveModel/Serializers/JSON/from_json
这篇关于从其json表示中获取IPAddr实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!