2013-04-20 77 views
1

我的目标是将一组对象序列化到一个文件中以创建备份。我有工作的开始,使用的机型方法(这里简化,假设我有两个ActiveRecords foo和bar):从文件中读取json序列化对象

def backup(file, foo, bar) 
    file.write(foo.to_json(root: true)) 
    file.write(bar.to_json(root: true)) 
end 

这给了我一个文件,我的愿望,在这种情况下,有两个记录:

{"foo":{"Account_id":1,"Name":"F","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}} 
{"bar":{"Account_id":1,"Name":"B","created_at":"2013-04-16T10:06:19Z","id":1,"updated_at":"2013-04-20T11:36:23Z"}} 

在以后的日子,然后我想读的备份和再次那些对象,可能再坚持他们回数据库。我的目标是迭代文件检查每个对象的类型,然后实例化正确的对象。我有部分的逻辑,但还没有完成,我还没有计算出如何在实例化之前确定每个序列化对象的类型。我有一个恢复代码如下:

def restore(file) 
    file.each_line do |line| 
    **<some magic that parses my line into objectType and objectHash>** 
    case objectType 
    when :foo 
     Foo.new.from_json(objectHash) 
     Foo.process 
     Foo.save! 
    when :bar 
     Bar.new.from_json(objectHash) 
     Bar.process 
     Bar.save! 
    end 
    end 
end 

我在找什么是在“一些魔术”部分去的位。我可以直接编写代码来直接解析这一行来确定它是一个foo还是一个bar,但是我觉得可能有一些棘手的Rails/Ruby方法来自动执行此操作。不幸的是,在这种情况下,Google不会成为我的朋友。我能看到的所有页面都集中在web请求中的json上,但不能以这种方式解析json。有什么我错过了,或者我应该直接编写代码来直接分割字符串并读取对象类型?

如果我写的代码字符串直接拆分,我会写线沿线的东西:

objectType = line[/^{"(\w*)"=>(.*)}/, 1] 
objectHash = line[/{"(\w*)"=>(.*)}/, 2] 

这是非常丑陋的,我敢肯定有一个更好的方法(这我仍然在寻找),但我不确定这是否是正确的方法v有一些东西会自动查看json表示形式,并从根值中知道要实例化的对象。

最后,使用from_json的实际实例也不起作用,它没有填充我的ActiveRecord上的任何字段。它给了我零参数,所以我认为解析语法是不正确的。

所以,这使得三个问题:

  1. 有没有一种方法来确定哪些对象是说我只是缺少,那就是干净多了?
  2. 如果没有,我需要使用正则表达式,是否有一种语法来获得在一次去解析行的两个位,而不是我的两行具有相同的正则表达式?
  3. from_json语法显得不愉快。有没有我在这里失踪的语法? (不再是一个问题 - 上面的代码是固定的,我使用as_json的时候应该是to_json,虽然文档上还不太清楚....)

(注:随着时间的推移编辑澄清我的问题,因为我现在已经得到了工作的正则表达式(以前没有),但仍不能确定这是非常优雅)

更多信息 - 的一个问题在这里,因为我掏了进去。此外,是as_json实际上并没有给我json - 我在文件中有一个散列,而不是json。此外,散列中created_at和lastupdated_at的值不会被引用 - 所以基本上这就是导致解析返回失败的原因。我已经解决了,我应该使用to_json而不是as_json,尽管文档表明as_json应该可以工作。

回答

0

我不确定我完全理解你的方法,但我认为使用JSON.parse()会有所帮助。

这里有http://mike.bailey.net.au/2011/02/json-with-ruby-and-rails/

一些好的信息,这将帮你翻译的原始对象回哈希。

+0

我认为JSON.parse()是您在不尝试将其放回到ActiveRecord时使用的内容,但是使用新的3.1功能您应该可以使用object.from_json()。除了这样做的文档非常稀少。 – PaulL 2013-04-20 22:36:53

+0

我已经更新了我的问题,使其更清晰(希望)我所要求的,并且我的文件将以任意顺序存储多个对象,所以我需要查看每一行以确定它是什么对象我正在阅读并实例化 – PaulL 2013-04-20 22:46:55

+0

我已经结束了使用JSON.parse(),它工作正常。我会尽快写一篇关于我的代码结束的文章。 – PaulL 2013-07-12 06:16:34

0

好的,所以我觉得我有一些工作。我并不确信它很优雅,但它给了我结果。我会花一些时间尝试使它更清洁。

的代码看起来是这样的:

file.each_line do |line| 
    objectType = line[/^{"(\w*)":(.*)}/, 1] 
    objectJSON = line[/{"(\w*)":(.*)}/, 2] 
    objectHash = JSON.parse(objectJSON) 
    case objectType 
    when 'foo' 
    restoredFoo = Foo.new(objectHash.except('id', 'created_at', 'updated_at')) 
    restoredFoo.created_at = objectHash['created_at'] 
    restoredFoo.updated_at = objectHash['updated_at'] 
    restoredFoo.save! 
    end 
    when 'bar' 
    restoredBar = Bar.new(objectHash.except('id', 'created_at', 'updated_at')) 
    restoredBar.created_at = objectHash['created_at'] 
    restoredBar.updated_at = objectHash['updated_at'] 
    restoredBar.save! 
    end 
end 

注意项目:

  1. 我觉得应该是创造,是不是一个JSON.parse对象的方式,而是将使用模型上的from_json方法。如果不这样做,我不确定from_json是什么好处!
  2. 我很喜欢mass_assignment。我真的不想使用:without_protection => true,尽管这是一个选项。我担心的是我确实希望created_at和updated_at恢复原样,但我想要一个新的ID。我将为我的应用程序中的许多实体执行此操作,但我并不想最终复制代码中的attributes_protected - 它看起来不是很干DRY
  3. 我仍然很确定我的reg exp可以同时给我objectType和objectJSON在一个电话

但说了这么多,它的工作,这是一个很好的一步向前。