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 15, 2023
1 parent 42e5c52 commit 9cfbbb4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
25 changes: 25 additions & 0 deletions lib/liquid/standardfilters.rb
Original file line number Diff line number Diff line change
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)

return 0 if ary.empty?

if property.nil?
# If we're doing an ordinary sum, all values must be numeric
raise(Liquid::ArgumentError, "cannot sum non-numeric values") unless ary.all? { |el| el.is_a?(Numeric) }
ary.sum
elsif ary.all? { |el| el.respond_to?(:[]) }
begin
ary.sum { |el| el[property] }
rescue TypeError
raise_property_error(property)
end
end
end

private

attr_reader :context
Expand Down
28 changes: 28 additions & 0 deletions test/integration/filter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,34 @@ def test_liquid_argument_error
assert_match(/\ALiquid error: wrong number of arguments /, exc.message)
assert_equal(exc.message, Template.parse(source).render)
end

def test_sum
src_w_prop = "{{ ary | sum: 'qty' }}"
src_wo_prop = "{{ ary | sum }}"

# [Without property] Test empty array
assert_template_result("0", src_wo_prop, { "ary" => [] })

# [Without property] Test array with only numeric elements
assert_template_result("6", src_wo_prop, { "ary" => [1, 2, 3] })

# [Without property] Test array with some non-numeric elements
with_non_num = { "ary" => [1, 2, "a", "b", { "qty" => 2 }] }
exc = assert_raises(Liquid::ArgumentError) do
Template.parse(src_wo_prop).render!(with_non_num)
end
assert_equal(exc.message, "Liquid error: cannot sum non-numeric values")
assert_equal(exc.message, Template.parse(src_wo_prop).render(with_non_num))

# [Without property] Test array with hashes, all of which have given property
assert_template_result("6", src_w_prop, { "ary" => [{ "qty" => 1 }, { "qty" => 2 }, { "qty" => 3 }] })

# [Without property] Test array with hashes, some of which do not have given property
exc = assert_raises(Liquid::ArgumentError) do
Template.parse(src_w_prop).render!("ary" => [{ "qty" => 1 }, { "qty" => 2 }, { "not_qty" => 3 }])
end
assert_equal(exc.message, "Liquid error: cannot select the property 'qty'")
end
end

class FiltersInTemplate < Minitest::Test
Expand Down

0 comments on commit 9cfbbb4

Please sign in to comment.