2014-12-04 41 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