Skip to content

Commit

Permalink
Add sum filter to standard filters
Browse files Browse the repository at this point in the history
  • Loading branch information
adamklingbaum committed Jun 19, 2023
1 parent 42e5c52 commit af66bc8
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
25 changes: 25 additions & 0 deletions lib/liquid/standardfilters.rb
Expand Up @@ -869,6 +869,31 @@ def default(input, default_value = '', options = {})
false_check || (input.respond_to?(:empty?) && input.empty?) ? default_value : input
end

# @liquid_public_docs
# @liquid_type filter
# @liquid_category array
# @liquid_summary
# Returns the sum of all elements in an array.
# @liquid_syntax array | sum
# @liquid_return [number]
def sum(input, property = nil)
ary = InputIterator.new(input, context)

if ary.empty?
0
elsif property.nil?
ary.sum do |item|
Utils.to_number(item)
end
else
ary.sum do |item|
item.respond_to?(:[]) ? Utils.to_number(item[property]) : 0
rescue TypeError
raise_property_error(property)
end
end
end

private

attr_reader :context
Expand Down
54 changes: 54 additions & 0 deletions test/integration/standard_filter_test.rb
Expand Up @@ -928,6 +928,60 @@ def test_where_no_target_value
assert_equal([{ "foo" => true }, { "foo" => "for sure" }], @filters.where(input, "foo"))
end

def test_sum_with_all_numbers
input = [1, 2]

assert_equal(3, @filters.sum(input))
assert_raises(Liquid::ArgumentError, "cannot select the property 'quantity'") do
@filters.sum(input, "quantity")
end
end

def test_sum_with_numeric_strings
input = [1, 2, "3", "4"]

assert_equal(10, @filters.sum(input))
assert_raises(Liquid::ArgumentError, "cannot select the property 'quantity'") do
@filters.sum(input, "quantity")
end
end

def test_sum_with_nested_arrays
input = [1, [2, [3, 4]]]

assert_equal(10, @filters.sum(input))
assert_raises(Liquid::ArgumentError, "cannot select the property 'quantity'") do
@filters.sum(input, "quantity")
end
end

def test_sum_with_indexable_map_values
input = [{ "quantity" => 1 }, { "quantity" => 2, "weight" => 3 }, { "weight" => 4 }]

assert_equal(0, @filters.sum(input))
assert_equal(3, @filters.sum(input, "quantity"))
assert_equal(7, @filters.sum(input, "weight"))
assert_equal(0, @filters.sum(input, "subtotal"))
end

def test_sum_with_indexable_non_map_values
input = [1, [2], "foo", { "quantity" => 3 }]

assert_equal(3, @filters.sum(input))
assert_raises(Liquid::ArgumentError, "cannot select the property 'quantity'") do
@filters.sum(input, "quantity")
end
end

def test_sum_with_unindexable_values
input = [1, true, nil, { "quantity" => 2 }]

assert_equal(1, @filters.sum(input))
assert_raises(Liquid::ArgumentError, "cannot select the property 'quantity'") do
@filters.sum(input, "quantity")
end
end

private

def with_timezone(tz)
Expand Down

0 comments on commit af66bc8

Please sign in to comment.