Command line calculator on Rails — dentaku

Итак, сегодня в моём блоге наконец появится первая запись по Ruby on Rails.

При разработке системы административного учёта для одного из моих клиентов на Rails я столкнулся с маленькой проблемой. Заказчик изъявил желание самостоятельно создавать новые тарифы, по которым производится расчёт платежей клиентов организации. Это значит что алгоритм работы тарифа не должен являться внутренней частью приложения. Необходимо пользователю дать возможность самостоятельно разрабатывать формулы, по которым и будут производиться расчёты. На самом деле это не проблема, это обычная практика — не обращаться же к программисту каждый раз, когда нужно изменить способ расчёта.

Для решения такой задачи тарифы легче всего хранить в виде:

ID      Name          Formula
1       rate1         var1+var2/var3
2       rate2         var1+var2/var3-100

При расчёте нужно просто извлечь формулу из БД, подставить переменные, рассчитать получившееся выражение и вывести результат пользователю. Самая большая сложность заключается именно на стадии «рассчитать получившееся выражение»…

В ход пошёл Google. Осознав, что найти простую и корректную функцию на Ruby (да и не только на Ruby), способную на входе принять нечто вроде «486+67/2-100», а результатом выдать «419,5», мне не удастся, я взялся за поиски информации на тему разработки простого синтаксического анализатора… И зря потерял время.

В Ruby on Rails не принято изобретать велосипед. Большинство велосипедов уже изобретено в виде гемов. Они хорошо хранятся, легко доступны и успешно причёсываются сообществом. Оказывается и мой велосипед давно изобретён. Называется он Dentaku.

Dentaku — это небольшой гем, позволяющий анализировать арифметические и логические выражения. На вход принимает строку типа «2+2*2», на выходе даёт результат операции «6».

Dentaku поддерживает работу с переменными и следующие операции:

  • Математические: + — * /
  • Логические: < > <= >= <> != = AND OR
  • Функции: IF ROUND

Для начала нужно его установить. На Rails 3 достаточно в Gemfile просто прописать:

gem 'dentaku'

А затем выполнить в директории проекта:

bundle install

После чего увидеть его в списке установленных гемов:

Теперь можно его использовать

def calculate
      calculator = Dentaku::Calculator.new
      calculator.evaluate("2+4") #простое выражение
      calculator.evaluate("2+4/4*8-3*6") #более сложное выражение
      calculator.evaluate("var1+4/4*8-var2*6", 
                           :var1 => 3, :var2 => 6) #выражение с переменными
end

 

Страница на Github — https://github.com/rubysolo/dentaku

Метки:, , , , , ,

Об авторе alvisx

Good muzhik.

Оставьте комментарий