Альтернативы "eval" для разбора даты ActiveSupport
Мой сценарий в настоящее время принимает строку даты ActiveSupport в качестве аргумента командной строки:
my_script --mindate 1.day
Внутри моего скрипта я использую eval для сохранения его в моей конфигурации
MyScript.configuration.min_date = eval(min_date_string)
Я понимаю, что это очень хитроумно и небезопасно, поскольку все можно передать eval, но каковы мои альтернативы?
2 ответа
Вы хотите продолжительность? Я полагаю, вы могли бы использовать ronic_duration.
my_script --mindate "1 day"
MyScript.configuration.min_date = ChronicDuration.parse(min_date_string)
Но поскольку это эвристика естественного языка, становится не совсем точно определенным, какие именно строки он распознает. Но он будет делать такие модные вещи, как "1 день и четыре часа".
Или вы можете написать свой собственный очень простой парсер / интерпретатор для аргумента. Просто разделите на пробел (для ввода типа "1 день") или период (для ввода "1 день"). Распознать несколько слов во второй позиции ("час", "минута", "день", "месяц", "год"), перевести их в секунды, умножить число на переведенное в секунды слово. Примерно дюжина линий рубина.
Или вы можете даже воспользоваться функцией ActiveSupport, которая поддерживает такие вещи, как "1.day", чтобы сделать ее еще проще.
str = "11 hours"
number, unit = str.split(' ')
number.to_i.send(unit)
Это позволило бы пользователю командной строки отправить любой метод на номер. Я не уверен, что это важно. В этом отношении я не уверен, если оригинал eval
действительно важно или нет - но я согласен с вами, это плохая практика. В этом отношении, вероятно, так send
на ввод пользователя, хотя и не так плохо.
Или вы можете просто заставить их посылать необработанное количество секунд и вычислять их сами.
my_script --mindate 86400
Ты осознаешь 1.day
в итоге просто переводится в количество секунд в стандартном дне, верно? Я не уверен, почему вы называете количество секунд "помнить", но это ваше дело!
edit Или еще одна альтернатива, заставьте их сделать:
my_script --mindays 2 --minhours 4 --minminutes 3
или что-то.
Как называется ваш сценарий? Всегда ли это будет вызываться пользователем с учетной записью на любой машине, на которой он запущен? Будет ли это вызываться веб-службой или таким образом, что кто-то, не имеющий доступа к машине, сможет вызывать ее удаленно со своими аргументами?
Если он будет вызываться только пользователями, и эти пользователи уже имеют доступ к ruby
команда или irb
тогда вы не позволяете им делать то, что они уже не могут сделать, вызывая eval.
Если он вызывается удаленно, вы, вероятно, не должны использовать eval. Или быстрое и грязное решение может заключаться в сопоставлении шаблонов, которые вы будете использовать с регулярным выражением. Что-то вроде /^[0-9]+(\.[a-z_0-9]+){,2}$/
перед оценкой убедитесь, что он находится в пределах 2 вызовов метода литерала Fixnum.