我正在使用元数据方法来处理一些代码。假设以下是一个字符串:
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
$ bmi被正确替换,但我希望代码能够执行。
答案 0 :(得分:6)
eval
方法会将您的字符串计算为Ruby代码。的 BUT ... 强>
您的字符串包含return
关键字,始终从方法调用返回。如果你在方法中eval
该字符串,那么它之后的任何代码都将永远不会运行,因为该方法将返回。如果您eval
在方法之外,则会出现LocalJumpError
异常,因为return
仅在方法内有效。我可以想象这会在你的代码中造成各种神秘的错误。
您说元数据来自您的身边,但是当您eval
时,您仍然会在代码中打开一个巨大的失败点,因为它可以完全符合任何。对eval
的一次调用可能会擦除整个磁盘,它可能会下载并运行漏洞利用程序,它甚至可能会将您的脚本重写为对人类产生仇恨的恶意AI。当你只想进行一些数值比较时,使用这种强大的方法确实没有意义。
实际上,使用eval
可能很好。您的代码将起作用,世界将不会结束。但即便如此也很糟糕,因为它创造了完全无法读取的代码。任何阅读你的剧本的程序员(包括你自己,六个月后当你回来修复某些东西)都会达到eval
并想到“呃......这究竟是做什么的?”在这种情况下,您应该始终在数据库中存储尽可能少的逻辑,并在代码中执行其余的计算。在这种情况下你会怎么做?我可以想到几个选择。
使用类似
的数据库架构table BMIIntervals (
MinValue Double,
Description String
)
您可以存储行
18.5, 'healthy'
25, 'overweight'
30, 'obese'
然后你可以在Ruby中轻松完成计算:
intervals = db.query("SELECT * FROM BMIIntervals ORDER BY MinValue DESC")
intervals.each { |row| return row[1] if $bmi >= row[0] }
return nil
或者如果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
然后您的元数据字符串只是"bmi"
而不是eval(metadata)
,您可以MetadataFuncs.send(metadata)
。通过这种方式,您可以确切地知道元数据可能调用的代码,即使没有查看数据库中的数据也是如此。