4

当有人提到通过编写inspect输出并通过加载将信息保存到外部文件的想法时eval,我看到很多人会批评这个想法,而是建议使用 YAML。编写输出的问题是什么inspect,为什么首选 YAML?对于人类可读性,我认为 rubyinspect​​ 或ppformat 优于 YAML。

4

3 回答 3

4

假设没有任何东西覆盖inspect,这有什么用?:

#<Foo:0xa34feb8 @bar="wat">

与此相比:

--- !ruby/object:Foo
bar: wat

在非平凡的情况下,YAML 更有可能产生有用的输出。它也是可移植的,并且可以用作在不同系统之间发送序列化数据的更可靠的方式。

于 2012-01-28T13:53:51.227 回答
4

安全是主要问题。因为eval将运行传递给它的任何代码,恶意黑客可以将代码注入您的数据文件,并控制您的程序。这对于您自己的小型脚本可能并不重要,但在 ruby​​ on rails 服务器中,安全性将很重要。假设我们有以下代码:

f=File.new("foobar.txt")
f.puts Foo.new.tap {|foo| foo.bar="bork"}.inspect

这将,假设Foohas not overwritten inspect,将给出如下内容:

#<Foo:0xff456a5 @bar="bork">

显然,这不是有效的 Ruby 语法。奇怪的是,eval没有抛出错误,只是返回nil。这只会使这成为一个更糟糕的主意,因为您期望成为的变量Foo现在只是nil(臭名昭著的NoMethodError: undefined method 'bork' for nil:NilClass错误)。

另一个大问题是安全问题。假设您的代码将数据保存到文件中,比如说foo.txt,并将inspected 哈希映射bars 存储到它们各自的bazes 中。需要知道这些映射以计划 FOO 约定的不同程序读取并发送eval此文件。想象一下,这个文件在黑客可以访问的地方(仔细想想,它几乎在任何地方)。如果这些程序在同时存储所有 foo 财务数据的 RoR 服务器上运行,黑客可能会造成大规模混乱。如果这个黑客将代码注入到foo.txt系统中,也就是说,将恶意病毒下载到系统中并安装它,但最后仍然留下原始程序的哈希值,它就会在不被注意的情况下执行。即使你eval的数据带有$SAFE=4,黑客仍然可以通过抛出错误等方式破坏foo刨程序的稳定性。

总而言之,虽然inspect-eval方法适用于基本类,例如Hash, String,Array等,但它依赖于类来给出其自身的精确句法表示。对于大多数应用程序(如果不是所有应用程序)来说,使用inspect-是个坏主意eval。YAML 是首选,因为它具有定义的数据语法,这意味着混入的可执行代码会导致错误,而不是被盲目地执行。此外,许多开发人员inspect用于调试,并且不希望对象提供自身的文件转储。

YAML 的其他好处是它可以轻松地序列化复杂的对象。使用 YAML 可以轻松实现 foos 和 bar 的复杂对象树,但使用inspect会产生巨大的复杂性。归根结底,这可以认为是 JSON 问题——因为eval使用了数据执行中的可执行代码。inspect对于您自己的小型实用程序可能很好,但永远不会在生产代码中,或者对广阔的世界开放的代码中。

于 2012-01-28T14:49:21.267 回答
1

我推荐 YAML,因为:

  1. 对于我们人类来说,它很容易理解,而不仅仅是一种语言。
  2. 它是一个标准,因此可以跨多种语言移植。
  3. 它支持标量、数组、散列以及字符串和数字。它还具有一些很酷的命名空间功能和别名,因此您可以重用定义并将数据视为单独的块。
  4. 再次参见#1 和#2。这些很重要。
于 2012-01-28T18:25:24.600 回答