mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
use BigDecimal on filters to have better precision
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
require 'cgi'
|
require 'cgi'
|
||||||
|
require 'bigdecimal'
|
||||||
|
|
||||||
module Liquid
|
module Liquid
|
||||||
|
|
||||||
@@ -210,41 +211,47 @@ module Liquid
|
|||||||
|
|
||||||
# addition
|
# addition
|
||||||
def plus(input, operand)
|
def plus(input, operand)
|
||||||
to_number(input) + to_number(operand)
|
apply_operation(input, operand, :+)
|
||||||
end
|
end
|
||||||
|
|
||||||
# subtraction
|
# subtraction
|
||||||
def minus(input, operand)
|
def minus(input, operand)
|
||||||
to_number(input) - to_number(operand)
|
apply_operation(input, operand, :-)
|
||||||
end
|
end
|
||||||
|
|
||||||
# multiplication
|
# multiplication
|
||||||
def times(input, operand)
|
def times(input, operand)
|
||||||
to_number(input) * to_number(operand)
|
apply_operation(input, operand, :*)
|
||||||
end
|
end
|
||||||
|
|
||||||
# division
|
# division
|
||||||
def divided_by(input, operand)
|
def divided_by(input, operand)
|
||||||
to_number(input) / to_number(operand)
|
apply_operation(input, operand, :/)
|
||||||
end
|
end
|
||||||
|
|
||||||
def modulo(input, operand)
|
def modulo(input, operand)
|
||||||
to_number(input) % to_number(operand)
|
apply_operation(input, operand, :%)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def to_number(obj)
|
def to_number(obj)
|
||||||
case obj
|
case obj
|
||||||
when Numeric
|
when Float
|
||||||
obj
|
BigDecimal.new(obj.to_s)
|
||||||
when String
|
when Numeric
|
||||||
(obj.strip =~ /^\d+\.\d+$/) ? obj.to_f : obj.to_i
|
obj
|
||||||
else
|
when String
|
||||||
0
|
(obj.strip =~ /^\d+\.\d+$/) ? BigDecimal.new(obj) : obj.to_i
|
||||||
end
|
else
|
||||||
|
0
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
Template.register_filter(StandardFilters)
|
Template.register_filter(StandardFilters)
|
||||||
|
|||||||
@@ -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_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 "6", "{{ '2.1' | times:3 | replace: '.','-' | plus:0}}"
|
||||||
|
|
||||||
|
assert_template_result "7.25", "{{ 0.0725 | times:100 }}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_divided_by
|
def test_divided_by
|
||||||
@@ -175,6 +177,8 @@ class StandardFiltersTest < Test::Unit::TestCase
|
|||||||
|
|
||||||
assert_template_result "5", "{{ 15 | divided_by:3 }}"
|
assert_template_result "5", "{{ 15 | divided_by:3 }}"
|
||||||
assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
|
assert_template_result "Liquid error: divided by 0", "{{ 5 | divided_by:0 }}"
|
||||||
|
|
||||||
|
assert_template_result "0.5", "{{ 2.0 | divided_by:4 }}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_modulo
|
def test_modulo
|
||||||
|
|||||||
Reference in New Issue
Block a user