mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
Fix clashing method names in enumerable drops
This commit is contained in:
+10
-1
@@ -54,7 +54,16 @@ module Liquid
|
|||||||
|
|
||||||
# Check for method existence without invoking respond_to?, which creates symbols
|
# Check for method existence without invoking respond_to?, which creates symbols
|
||||||
def self.invokable?(method_name)
|
def self.invokable?(method_name)
|
||||||
@invokable_methods ||= Set.new(["to_liquid"] + (public_instance_methods - Liquid::Drop.public_instance_methods).map(&:to_s))
|
unless @invokable_methods
|
||||||
|
blacklist = Liquid::Drop.public_instance_methods + [:each]
|
||||||
|
if include?(Enumerable)
|
||||||
|
blacklist += Enumerable.public_instance_methods
|
||||||
|
blacklist -= [:sort, :count, :first, :min, :max]
|
||||||
|
end
|
||||||
|
# Ruby 1.8 compatibility: call to_s on method names (which are strings in 1.8, but already symbols in 1.9)
|
||||||
|
whitelist = [:to_liquid] + (public_instance_methods.map(&:to_s) - blacklist.map(&:to_s))
|
||||||
|
@invokable_methods = Set.new(whitelist.map(&:to_s))
|
||||||
|
end
|
||||||
@invokable_methods.include?(method_name.to_s)
|
@invokable_methods.include?(method_name.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ class ProductDrop < Liquid::Drop
|
|||||||
end
|
end
|
||||||
|
|
||||||
class EnumerableDrop < Liquid::Drop
|
class EnumerableDrop < Liquid::Drop
|
||||||
|
def before_method(method)
|
||||||
|
method
|
||||||
|
end
|
||||||
|
|
||||||
def size
|
def size
|
||||||
3
|
3
|
||||||
@@ -67,6 +70,20 @@ class EnumerableDrop < Liquid::Drop
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class RealEnumerableDrop < Liquid::Drop
|
||||||
|
include Enumerable
|
||||||
|
|
||||||
|
def before_method(method)
|
||||||
|
method
|
||||||
|
end
|
||||||
|
|
||||||
|
def each
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
yield 3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class DropsTest < Test::Unit::TestCase
|
class DropsTest < Test::Unit::TestCase
|
||||||
include Liquid
|
include Liquid
|
||||||
|
|
||||||
@@ -170,6 +187,27 @@ class DropsTest < Test::Unit::TestCase
|
|||||||
assert_equal '3', Liquid::Template.parse( '{{collection.size}}').render('collection' => EnumerableDrop.new)
|
assert_equal '3', Liquid::Template.parse( '{{collection.size}}').render('collection' => EnumerableDrop.new)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_enumerable_drop_will_invoke_before_method_for_clashing_method_names
|
||||||
|
["select", "each", "map", "cycle"].each do |method|
|
||||||
|
assert_equal method.to_s, Liquid::Template.parse("{{collection.#{method}}}").render('collection' => EnumerableDrop.new)
|
||||||
|
assert_equal method.to_s, Liquid::Template.parse("{{collection[\"#{method}\"]}}").render('collection' => EnumerableDrop.new)
|
||||||
|
assert_equal method.to_s, Liquid::Template.parse("{{collection.#{method}}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
assert_equal method.to_s, Liquid::Template.parse("{{collection[\"#{method}\"]}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_some_enumerable_methods_still_get_invoked
|
||||||
|
[ :count, :max ].each do |method|
|
||||||
|
assert_equal "3", Liquid::Template.parse("{{collection.#{method}}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
assert_equal "3", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
end
|
||||||
|
|
||||||
|
[ :min, :first ].each do |method|
|
||||||
|
assert_equal "1", Liquid::Template.parse("{{collection.#{method}}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
assert_equal "1", Liquid::Template.parse("{{collection[\"#{method}\"]}}").render('collection' => RealEnumerableDrop.new)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_empty_string_value_access
|
def test_empty_string_value_access
|
||||||
assert_equal '', Liquid::Template.parse('{{ product[value] }}').render('product' => ProductDrop.new, 'value' => '')
|
assert_equal '', Liquid::Template.parse('{{ product[value] }}').render('product' => ProductDrop.new, 'value' => '')
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user