use BigDecimal on filters to have better precision

This commit is contained in:
Arthur Neves
2013-06-05 16:09:05 -04:00
parent f4fb2f159c
commit ab760649ee
2 changed files with 25 additions and 14 deletions

View File

@@ -1,4 +1,5 @@
require 'cgi'
require 'bigdecimal'
module Liquid
@@ -210,41 +211,47 @@ module Liquid
# addition
def plus(input, operand)
to_number(input) + to_number(operand)
apply_operation(input, operand, :+)
end
# subtraction
def minus(input, operand)
to_number(input) - to_number(operand)
apply_operation(input, operand, :-)
end
# multiplication
def times(input, operand)
to_number(input) * to_number(operand)
apply_operation(input, operand, :*)
end
# division
def divided_by(input, operand)
to_number(input) / to_number(operand)
apply_operation(input, operand, :/)
end
def modulo(input, operand)
to_number(input) % to_number(operand)
apply_operation(input, operand, :%)
end
private
def to_number(obj)
case obj
when Numeric
obj
when String
(obj.strip =~ /^\d+\.\d+$/) ? obj.to_f : obj.to_i
else
0
end
def to_number(obj)
case obj
when Float
BigDecimal.new(obj.to_s)
when Numeric
obj
when String
(obj.strip =~ /^\d+\.\d+$/) ? BigDecimal.new(obj) : obj.to_i
else
0
end
end
def apply_operation(input, operand, operation)
result = to_number(input).send(operation, to_number(operand))
result.is_a?(BigDecimal) ? result.to_f : result
end
end
Template.register_filter(StandardFilters)

View File

@@ -164,6 +164,8 @@ class StandardFiltersTest < Test::Unit::TestCase
assert_match(/(6\.3)|(6\.(0{13})1)/, Template.parse("{{ '2.1' | times:3 }}").render)
assert_template_result "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
end
def test_divided_by
@@ -175,6 +177,8 @@ class StandardFiltersTest < Test::Unit::TestCase
assert_template_result "5", "{{ 15 | divided_by:3 }}"
assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
end
def test_modulo