mirror of
https://github.com/kemko/liquid.git
synced 2026-01-01 15:55:40 +03:00
Merge pull request #1026 from Shopify/where-filter
Add `where` filter to standard filters
This commit is contained in:
@@ -171,6 +171,20 @@ module Liquid
|
||||
end
|
||||
end
|
||||
|
||||
# Filter the elements of an array to those with a certain property value.
|
||||
# By default the target is any truthy value.
|
||||
def where(input, property, target_value = nil)
|
||||
ary = InputIterator.new(input)
|
||||
|
||||
if ary.empty?
|
||||
[]
|
||||
elsif ary.first.respond_to?(:[]) && target_value.nil?
|
||||
ary.where_present(property)
|
||||
elsif ary.first.respond_to?(:[])
|
||||
ary.where(property, target_value)
|
||||
end
|
||||
end
|
||||
|
||||
# Remove duplicate elements from an array
|
||||
# provide optional property with which to determine uniqueness
|
||||
def uniq(input, property = nil)
|
||||
@@ -449,6 +463,24 @@ module Liquid
|
||||
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
|
||||
end
|
||||
end
|
||||
|
||||
def where(property, target_value)
|
||||
select do |item|
|
||||
item[property] == target_value
|
||||
end
|
||||
rescue TypeError
|
||||
# Cannot index with the given property type (eg. indexing integers with strings
|
||||
# which are only allowed to be indexed by other integers).
|
||||
raise ArgumentError.new("cannot select the property `#{property}`")
|
||||
end
|
||||
|
||||
def where_present(property)
|
||||
select { |item| item[property] }
|
||||
rescue TypeError
|
||||
# Cannot index with the given property type (eg. indexing integers with strings
|
||||
# which are only allowed to be indexed by other integers).
|
||||
raise ArgumentError.new("cannot select the property `#{property}`")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -614,6 +614,78 @@ class StandardFiltersTest < Minitest::Test
|
||||
assert_template_result('abc', "{{ 'abc' | date: '%D' }}")
|
||||
end
|
||||
|
||||
def test_where
|
||||
input = [
|
||||
{ "handle" => "alpha", "ok" => true },
|
||||
{ "handle" => "beta", "ok" => false },
|
||||
{ "handle" => "gamma", "ok" => false },
|
||||
{ "handle" => "delta", "ok" => true }
|
||||
]
|
||||
|
||||
expectation = [
|
||||
{ "handle" => "alpha", "ok" => true },
|
||||
{ "handle" => "delta", "ok" => true }
|
||||
]
|
||||
|
||||
assert_equal expectation, @filters.where(input, "ok", true)
|
||||
assert_equal expectation, @filters.where(input, "ok")
|
||||
end
|
||||
|
||||
def test_where_no_key_set
|
||||
input = [
|
||||
{ "handle" => "alpha", "ok" => true },
|
||||
{ "handle" => "beta" },
|
||||
{ "handle" => "gamma" },
|
||||
{ "handle" => "delta", "ok" => true }
|
||||
]
|
||||
|
||||
expectation = [
|
||||
{ "handle" => "alpha", "ok" => true },
|
||||
{ "handle" => "delta", "ok" => true }
|
||||
]
|
||||
|
||||
assert_equal expectation, @filters.where(input, "ok", true)
|
||||
assert_equal expectation, @filters.where(input, "ok")
|
||||
end
|
||||
|
||||
def test_where_non_array_map_input
|
||||
assert_equal [{ "a" => "ok" }], @filters.where({ "a" => "ok" }, "a", "ok")
|
||||
assert_equal [], @filters.where({ "a" => "not ok" }, "a", "ok")
|
||||
end
|
||||
|
||||
def test_where_indexable_but_non_map_value
|
||||
assert_raises(Liquid::ArgumentError) { @filters.where(1, "ok", true) }
|
||||
assert_raises(Liquid::ArgumentError) { @filters.where(1, "ok") }
|
||||
end
|
||||
|
||||
def test_where_non_boolean_value
|
||||
input = [
|
||||
{ "message" => "Bonjour!", "language" => "French" },
|
||||
{ "message" => "Hello!", "language" => "English" },
|
||||
{ "message" => "Hallo!", "language" => "German" }
|
||||
]
|
||||
|
||||
assert_equal [{ "message" => "Bonjour!", "language" => "French" }], @filters.where(input, "language", "French")
|
||||
assert_equal [{ "message" => "Hallo!", "language" => "German" }], @filters.where(input, "language", "German")
|
||||
assert_equal [{ "message" => "Hello!", "language" => "English" }], @filters.where(input, "language", "English")
|
||||
end
|
||||
|
||||
def test_where_array_of_only_unindexable_values
|
||||
assert_nil @filters.where([nil], "ok", true)
|
||||
assert_nil @filters.where([nil], "ok")
|
||||
end
|
||||
|
||||
def test_where_no_target_value
|
||||
input = [
|
||||
{ "foo" => false },
|
||||
{ "foo" => true },
|
||||
{ "foo" => "for sure" },
|
||||
{ "bar" => true }
|
||||
]
|
||||
|
||||
assert_equal [{ "foo" => true }, { "foo" => "for sure" }], @filters.where(input, "foo")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_timezone(tz)
|
||||
|
||||
Reference in New Issue
Block a user