Я создаю простое приложение для опроса Ruby on Rails для проекта психологического опроса друга. Итак, у нас есть опросы, в каждом опросе есть куча вопросов, и у каждого вопроса есть один из вариантов, который могут выбрать участники. Ничего захватывающего.
Одним из интересных аспектов является то, что каждый вариант ответа имеет связанное с ним значение балла. Таким образом, для каждого опроса необходимо рассчитать общий балл на основе этих значений.
Теперь моя идея состоит в том, чтобы вместо жестко закодированных расчетов позволить пользователю добавить формулу, по которой будет рассчитываться общий балл опроса. Примеры формул:
"Q1 + Q2 + Q3"
"(Q1 + Q2 + Q3) / 3"
"(10 - Q1) + Q2 + (Q3 * 2)"
Так что просто базовая математика (с некоторыми дополнительными скобками для ясности). Идея состоит в том, чтобы формулы были очень простыми, чтобы любой, кто владеет базовой математикой, мог вводить их, не прибегая к причудливому синтаксису.
Моя идея состоит в том, чтобы взять любую заданную формулу и заменить заполнители, такие как Q1, Q2 и т. д., на значения баллов, основанные на том, что выбирает участник. И затем eval() только что сформированная строка. Что-то вроде этого:
f = "(Q1 + Q2 + Q3) / 2" # some crazy formula for this survey
values = {:Q1 => 1, :Q2 => 2, :Q3 => 2} # values for substitution
result = f.gsub(/(Q\d+)/) {|m| values[$1.to_sym] } # string to be eval()-ed
eval(result)
Итак, мои вопросы:
Есть лучший способ это сделать? Я открыт для любых предложений.
Как обрабатывать формулы, в которых не все заполнители были успешно заменены (например, не был дан ответ на один вопрос)? Пример:
{:Q2 => 2}
не было в хэше значений? Моя идея состояла в том, чтобы спасти eval(), но в этом случае это не подведет, потому что(1 + + 2) / 2
все еще может быть обработано eval()... есть мысли?Как добиться должного результата? Должно быть 2,5, но из-за целочисленной арифметики оно будет усечено до 2. Я не могу ожидать, что люди, предоставившие правильную формулу (например, / 2,0 ), поймут этот нюанс.
Я не ожидаю этого, но как лучше всего защитить eval() от злоупотреблений (например, неверная формула, ввод манипулируемых значений)? Пример:
f = 'system("ruby -v"); (Q1 + (Q2 / 3) + Q3 + (Q4 * 2)) / 2 '
Благодарю вас!