mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-19 19:00:39 -07: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
|
||||||
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
|
# Remove duplicate elements from an array
|
||||||
# provide optional property with which to determine uniqueness
|
# provide optional property with which to determine uniqueness
|
||||||
def uniq(input, property = nil)
|
def uniq(input, property = nil)
|
||||||
@@ -449,6 +463,24 @@ module Liquid
|
|||||||
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
|
yield(e.respond_to?(:to_liquid) ? e.to_liquid : e)
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -614,6 +614,78 @@ class StandardFiltersTest < Minitest::Test
|
|||||||
assert_template_result('abc', "{{ 'abc' | date: '%D' }}")
|
assert_template_result('abc', "{{ 'abc' | date: '%D' }}")
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def with_timezone(tz)
|
def with_timezone(tz)
|
||||||
|
|||||||
Reference in New Issue
Block a user