我正在使用元数据方法来处理一些代码.假设以下是一个字符串:
if $bmi >= 18.5 && $bmi <= 24.9 then return 'healthy' elsif $bmi >= 25 && $bmi <= 29.9 then return 'overweight' elsif $bmi > 30 then return 'obese' end
Run Code Online (Sandbox Code Playgroud)
$ bmi被正确替换,但我希望代码执行.
该eval方法将您的字符串评估为Ruby代码.但...
您的字符串包含return关键字,该关键字始终从方法调用返回.如果你eval在方法中使用该字符串,那么它之后的任何代码都将永远不会运行,因为该方法将返回.如果你eval在方法之外,你会得到一个LocalJumpError例外,因为return它只在方法中有效.我可以想象这会导致代码中出现各种神秘错误.
你说元数据来自你的身边,但你仍然在你的代码中打开一个巨大的失败点,eval因为它可以做任何事情.那一个调用eval可以擦除整个磁盘,它可以下载并运行一个漏洞,它甚至可以将你的脚本重写成一个仇恨人类的恶意AI.当你只想进行一些数值比较时,使用这种强大的方法确实没有意义.
实际上,你可能很好用eval.您的代码将起作用,世界将不会结束.但即便如此,它也很糟糕,因为它创造了完全无法读取的代码.任何阅读你的剧本的程序员(包括你自己,六个月后你回来修理一些东西)都会达到这个目标,eval并想"呃......这究竟是做什么的?" 在这种情况下,您应该始终在数据库中存储尽可能少的逻辑,并在代码中执行其余的计算.在这种情况下你会怎么做?我可以想到几个选择.
使用DB模式
table BMIIntervals (
MinValue Double,
Description String
)
Run Code Online (Sandbox Code Playgroud)
您可以存储行
18.5, 'healthy'
25, 'overweight'
30, 'obese'
Run Code Online (Sandbox Code Playgroud)
然后你可以轻松地在Ruby中进行计算:
intervals = db.query("SELECT * FROM BMIIntervals ORDER BY MinValue DESC")
intervals.each { |row| return row[1] if $bmi >= row[0] }
return nil
Run Code Online (Sandbox Code Playgroud)
或者如果BMI间隔是固定的,并且元数据说明要做什么样的计算,您可以简单地在Ruby中定义计算:
module MetadataFuncs
def self.bmi
return 'obese' if $bmi > 30
return 'overweight' if $bmi >= 25
return 'healthy' if $bmi >= 18.5
end
end
Run Code Online (Sandbox Code Playgroud)
然后你的元数据字符串将是正确的"bmi",而不是eval(metadata)你可以做到的MetadataFuncs.send(metadata).通过这种方式,您可以确切地知道元数据可能调用的代码,即使没有查看数据库中的数据.
| 归档时间: |
|
| 查看次数: |
949 次 |
| 最近记录: |