2014-12-04 40 views
0

参数假设我有一个方法访问哈希键作为EVAL

def test_eval(formula, num) 
    eval(formula) 
end 

那么我可以说

p test_eval("2 + num", 3) 

并在EVAL过程中它会看到num被定义为3在这种情况下,将打印出5.

假设我想在我的公式中允许任意变量名称。例如,我要评估公式

test_eval("2 + num1 + num2", 3, 5) 

我可以修改方法签名接受两个参数叫做num1num2,但有给我,而不必硬编码签名,简单地接受的方式变量名称的散列?

例如

test_eval("2 + num1 + num2", {:num1 => 3, :num2 => 5}) 

而且我的方法将评估公式和返回10.如何定义,让我拨打这个电话,并返回相应的结果的方法?

+0

为什么你需要做到这一点呢?我怀疑你已经决定''eval'是解决方案,现在你正试图让它工作,当你可能会更好地备份和重新开始。 – 2014-12-04 21:07:22

+0

@ muistooshort'eval'绝对是最容易想到的解决方案,因为我很有兴趣允许其他人在公式的上下文中传递自己的公式以及他们自己的变量。公式可以是任意的ruby代码,而不是像数学公式分析器那样的特定的东西。 – MxyL 2014-12-04 21:10:51

回答

0
def test_eval(formula, params) 
    params.each do |key, value| 
    formula = formula.gsub(key.to_s,value.to_s) 
    end 

    eval(formula) 
end 
+1

当你test_eval('a + aa',:a => 1,:aa => 2)'时会发生什么?这种方法还有很多其他漏洞。 – 2014-12-04 21:05:25

1
def test_eval(formula, **bindings) 
    b = binding 
    bindings.each do |var, val| b.local_variable_set(var, val) end 

    b.eval(formula) 
end 

test_eval('2 + num1 + num2', num1: 3, num2: 5) 
# => 10 

我不与他人同意,但:这不是一个好主意:

test_eval('`rm -rf /` # Oops.') 
+0

如果我使用'$ SAFE'来保护它,该怎么办?会不会更好(或不是那么糟糕)? – MxyL 2014-12-04 23:42:43

+0

不是。 '$ SAFE'不安全。这是一个插件,是一个事后的想法。像这样的功能必须从一开始就内置。 '$ SAFE'有漏洞。一般来说,您不应该仅仅依赖于Ruby内置的隔离功能,而应该在Ruby之外使用一些隔离。例如,您可以在两个独立的AppDomain中运行两个IronRuby实例。或者在不同的安全上下文中运行两个JRuby实例。或者在两个独立的OS进程中运行两个Rubinius/YARV /实例。依靠.NET,Java或操作系统的隔离功能,而不是(或者除了)Ruby的。 – 2014-12-04 23:47:39

+0

如果任意用户不提供输入,那么评估仍然是一个问题? – MxyL 2014-12-05 17:36:50