From 761c2b3a100430149557ff6a3a93ae89c47e28d6 Mon Sep 17 00:00:00 2001 From: Eric Chan Date: Tue, 11 Feb 2020 03:05:07 -0500 Subject: [PATCH] allow method literals to provide useful values --- lib/liquid/condition.rb | 12 ++------- lib/liquid/expression.rb | 26 +++++++++++++----- test/integration/tags/statements_test.rb | 34 ++++++++++++++++++++++++ test/integration/variable_test.rb | 27 +++++++++++++++++++ 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/lib/liquid/condition.rb b/lib/liquid/condition.rb index 67582632a..00eb2493e 100644 --- a/lib/liquid/condition.rb +++ b/lib/liquid/condition.rb @@ -92,19 +92,11 @@ def inspect def equal_variables(left, right) if left.is_a?(Liquid::Expression::MethodLiteral) - if right.respond_to?(left.method_name) - return right.send(left.method_name) - else - return nil - end + return left.test(right) end if right.is_a?(Liquid::Expression::MethodLiteral) - if left.respond_to?(right.method_name) - return left.send(right.method_name) - else - return nil - end + return right.test(left) end left == right diff --git a/lib/liquid/expression.rb b/lib/liquid/expression.rb index 9670906b8..817857e3f 100644 --- a/lib/liquid/expression.rb +++ b/lib/liquid/expression.rb @@ -3,15 +3,29 @@ module Liquid class Expression class MethodLiteral - attr_reader :method_name, :to_s + attr_reader :to_liquid - def initialize(method_name, to_s) + def initialize(method_name, to_liquid) @method_name = method_name - @to_s = to_s + @to_liquid = to_liquid end - def to_liquid - to_s + def to_s + to_liquid.to_s + end + + def test(other) + other.respond_to?(@method_name) && other.send(@method_name) || self == other + end + end + + class EmptyLiteral < MethodLiteral + include Enumerable + + def each; end + + def to_ary + to_liquid end end @@ -20,7 +34,7 @@ def to_liquid 'true' => true, 'false' => false, 'blank' => MethodLiteral.new(:blank?, '').freeze, - 'empty' => MethodLiteral.new(:empty?, '').freeze + 'empty' => EmptyLiteral.new(:empty?, [].freeze).freeze }.freeze SINGLE_QUOTED_STRING = /\A'(.*)'\z/m diff --git a/test/integration/tags/statements_test.rb b/test/integration/tags/statements_test.rb index d1c55c991..4a00837ef 100644 --- a/test/integration/tags/statements_test.rb +++ b/test/integration/tags/statements_test.rb @@ -2,17 +2,27 @@ require 'test_helper' +class EmptyDrop < Liquid::Drop + def empty? + true + end +end + class StatementsTest < Minitest::Test include Liquid def test_true_eql_true text = ' {% if true == true %} true {% else %} false {% endif %} ' assert_template_result(' true ', text) + text = ' {% if var == true %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'var' => true) end def test_true_not_eql_true text = ' {% if true != true %} true {% else %} false {% endif %} ' assert_template_result(' false ', text) + text = ' {% if var != true %} true {% else %} false {% endif %} ' + assert_template_result(' false ', text, 'var' => true) end def test_true_lq_true @@ -93,6 +103,30 @@ def test_is_collection_empty def test_is_not_collection_empty text = ' {% if array == empty %} true {% else %} false {% endif %} ' assert_template_result(' false ', text, 'array' => [1, 2, 3]) + + text = ' {% if array != empty %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'array' => [1, 2, 3]) + end + + def test_is_collection_empty_backward + text = ' {% if empty == array %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'array' => []) + end + + def test_is_string_empty + text = ' {% if string == empty %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'string' => '') + + text = ' {% if empty == string %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'string' => '') + end + + def test_is_non_array_empty + text = ' {% if obj == empty %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'obj' => EmptyDrop.new) + + text = ' {% if empty == obj %} true {% else %} false {% endif %} ' + assert_template_result(' true ', text, 'obj' => EmptyDrop.new) end def test_nil diff --git a/test/integration/variable_test.rb b/test/integration/variable_test.rb index 45268bdd3..71922698e 100644 --- a/test/integration/variable_test.rb +++ b/test/integration/variable_test.rb @@ -34,6 +34,33 @@ def test_using_blank_as_variable_name def test_using_empty_as_variable_name template = Template.parse("{% assign foo = empty %}{{ foo }}") assert_equal('', template.render!) + template = Template.parse("{% assign foo = empty %}{% if foo == ary %}Y{% else %}N{% endif %}") + assert_equal('Y', template.render!('ary' => [])) + template = Template.parse("{% assign foo = empty %}{% if foo == foo %}Y{% else %}N{% endif %}") + assert_equal('Y', template.render!) + template = Template.parse("{% if empty == empty %}Y{% else %}N{% endif %}") + assert_equal('Y', template.render!) + end + + def test_using_empty_as_variable_name_with_filters + template = Template.parse("{% assign foo = empty %}{{ foo | sort | size }}") + assert_equal('0', template.render!) + template = Template.parse("{% assign foo = empty | sort %}{{ foo | size }}") + assert_equal('0', template.render!) + end + + def test_using_empty_as_empty_array + template = Template.parse("{% for x in empty %}x{% endfor %}") + assert_equal('', template.render!) + end + + def test_empty_can_be_filled + template = Template.parse("{% assign foo = empty %}{{ foo | concat: bar }}") + assert_equal('Y', template.render!('bar' => ['Y'])) + template = Template.parse("{% assign foo = empty %}{{ foo | concat: bar | join: '--' }}") + assert_equal('A--B', template.render!('bar' => ['A', 'B'])) + template = Template.parse("{% assign foo = empty %}{% assign tar = foo | concat: bar %}{{ tar | join: '--' }}{{ tar | size }}") + assert_equal('A--B2', template.render!('bar' => ['A', 'B'])) end def test_hash_scoping