ActiveSupport 日期解析的 "eval" 替代方案

Alternatives to "eval" for ActiveSupport date parsing

我的脚本当前接受 ActiveSupport 日期字符串作为命令行参数:

my_script --mindate 1.day

在我的脚本中,我使用 eval 将其存储到我的配置中

MyScript.configuration.min_date = eval(min_date_string)

我知道这是非常狡猾和不安全的,因为任何东西都可以传递给 eval,但我有什么选择?

你想要持续时间?我想你可以使用 chronic_duration

 my_script --mindate "1 day"
 MyScript.configuration.min_date = ChronicDuration.parse(min_date_string)

但由于它是自然语言启发式算法,因此无法完全准确地定义它将识别哪些类型的字符串。但它会做一些奇特的事情,比如“1 天 4 小时”。

或者您可以为参数编写自己的非常简单的 parser/interpreter。只需拆分 space(对于“1 天”类型的输入)或句点(对于“1.day”)类型的输入。识别第二个位置的几个单词("hour"、"minute"、"day"、"month"、"year"),将它们翻译成秒,将数字乘以翻译后的数字秒字。大概有十几行 ruby 。

或者您甚至可以利用支持“1.day”之类内容的 ActiveSupport 功能,使其更加轻松。

  str = "11 hours"
  number, unit = str.split(' ')
  number.to_i.send(unit)

这将使命令行用户可以将他们想要的任何方法发送到一个号码。我不确定这是否重要。就此而言,我不确定原来的 eval 是否真的重要——但我同意你的看法,这是不好的做法。就此而言,用户输入的 send 可能也是如此,尽管还没有那么糟糕。

或者您可以让他们发送原始秒数并自行计算。

my_script --mindate 86400

你知道 1.day 最终只是转换为标准日的秒数,对吧?我不确定你为什么要调用秒数 "mindate",但那是你的事!

编辑 或者另一种选择,让他们做:

my_script --mindays 2 --minhours 4 --minminutes 3

之类的。

你的脚本是如何被调用的?这是否总是由在 运行 任何机器上拥有帐户的用户调用?这是否会以某种方式被 Web 服务调用,或者以某种方式无法访问机器的人能够使用他们自己的参数远程调用它?

如果它只会被用户调用,并且这些用户已经可以访问 ruby 命令或 irb,那么您不会让他们做任何他们可以做的事情'还没有通过调用 eval 来完成。

如果是远程调用,您可能不应该使用 eval。或者,一个快速而肮脏的解决方案可能是匹配您将使用正则表达式评估的模式。 /^[0-9]+(\.[a-z_0-9]+){,2}$/ 之类的东西会确保它在评估之前在 Fixnum 文字的 2 次方法调用内。