当有人提到通过编写inspect
输出并通过eval
加载来保存信息到外部文件的想法时,我看到许多人会批评这个想法,而是推荐使用YAML。编写inspect
的输出有什么问题,为什么YAML更受欢迎?为了人类的可读性,我认为ruby inspect
或pp
格式优于YAML。
答案 0 :(得分:4)
假设没有覆盖inspect
,这有什么用处?:
#<Foo:0xa34feb8 @bar="wat">
与此相比:
--- !ruby/object:Foo
bar: wat
YAML更有可能在非平凡的情况下产生有用的输出。它也是可移植的,可以用作在不同系统之间发送序列化数据的更可靠方式。
答案 1 :(得分:4)
安全是主要关注点。因为eval
将运行传递给它的任何代码,恶意黑客可以将代码注入您的数据文件,并控制您的程序。这对于自己的小脚本可能并不重要,但在rails服务器上的ruby中,安全性将非常重要。想象一下,我们有以下代码:
f=File.new("foobar.txt")
f.puts Foo.new.tap {|foo| foo.bar="bork"}.inspect
假设Foo
没有覆盖inspect
,这会产生这样的结果:
#<Foo:0xff456a5 @bar="bork">
显然,这不是有效的Ruby语法。奇怪的是,eval
不会引发任何错误,只会返回nil
。这只是一个更糟糕的想法,因为你期望成为Foo
的变量现在只是nil
(臭名昭着的NoMethodError: undefined method 'bork' for nil:NilClass
错误)。
另一个大问题是安全问题。假设您的代码将数据保存到文件中,比方说foo.txt
,并将inspect
ed哈希映射bar
存储到各自的baz
es。需要知道这些映射来规划FOO约定的另一个程序会读取eval
这个文件。想象一下,这个文件是黑客可以访问它的地方(当你想到它时,几乎可以在任何地方)。如果这些程序在同时存储所有foo财务数据的RoR服务器上运行,则黑客可能会导致大规模混乱。如果这个黑客将代码注入foo.txt
,比如说,将恶意病毒下载到系统并安装它,但最后仍然保留了原始程序的哈希,那么它就会被忽视。即使您使用eval
$SAFE=4
数据,黑客仍然可以通过抛出错误等来破坏foo计划程序的稳定性。
总而言之,虽然inspect
- eval
方法适用于基本类,例如Hash
,String
,Array
等,但它取决于在类上给出自己的完全语法表示。对于大多数(如果不是所有)应用程序,使用inspect
- eval
是个坏主意。 YAML是首选,因为它具有 data 的已定义语法,这意味着混合的可执行代码会导致错误,而不是无意识地执行。此外,许多开发人员使用inspect
进行调试,并且不希望对象提供自己的文件转储。
YAML的其他好处是它可以轻松地序列化复杂对象。使用YAML可以很容易地使用复杂的foos和bars对象树,但使用inspect
会产生巨大的复杂性。在最后的分析中,这可以被认为是JSON问题 - 由于使用eval
而执行的数据中的可执行代码。 inspect
对于自己的小实用程序可能没问题,但从不在生产代码中,或者代码可以在广阔的世界范围内开放。
答案 2 :(得分:1)
我推荐YAML,因为: