From e361a4d53c6770e70795c760d53794bfc536354a Mon Sep 17 00:00:00 2001 From: Michael Go Date: Wed, 26 May 2021 17:27:18 -0300 Subject: [PATCH] introduce to_liquid_value on variable look and conditional statements --- lib/liquid/tags/case.rb | 9 +++++++- lib/liquid/tags/if.rb | 6 ++++- lib/liquid/tags/unless.rb | 11 +++++++-- lib/liquid/utils.rb | 8 +++++++ lib/liquid/variable_lookup.rb | 3 +++ test/integration/variable_test.rb | 29 +++++++++++++++++++++++ test/test_helper.rb | 38 +++++++++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 4 deletions(-) diff --git a/lib/liquid/tags/case.rb b/lib/liquid/tags/case.rb index ccd69bd..d6ab64e 100644 --- a/lib/liquid/tags/case.rb +++ b/lib/liquid/tags/case.rb @@ -52,7 +52,14 @@ module Liquid @blocks.each do |block| if block.else? block.attachment.render_to_output_buffer(context, output) if execute_else_block - elsif block.evaluate(context) + next + end + + result = Liquid::Utils.to_liquid_value( + block.evaluate(context) + ) + + if result execute_else_block = false block.attachment.render_to_output_buffer(context, output) end diff --git a/lib/liquid/tags/if.rb b/lib/liquid/tags/if.rb index 44aea61..f4b57d7 100644 --- a/lib/liquid/tags/if.rb +++ b/lib/liquid/tags/if.rb @@ -50,7 +50,11 @@ module Liquid def render_to_output_buffer(context, output) @blocks.each do |block| - if block.evaluate(context) + result = Liquid::Utils.to_liquid_value( + block.evaluate(context) + ) + + if result return block.attachment.render_to_output_buffer(context, output) end end diff --git a/lib/liquid/tags/unless.rb b/lib/liquid/tags/unless.rb index f67f57a..a799c82 100644 --- a/lib/liquid/tags/unless.rb +++ b/lib/liquid/tags/unless.rb @@ -11,13 +11,20 @@ module Liquid def render_to_output_buffer(context, output) # First condition is interpreted backwards ( if not ) first_block = @blocks.first - unless first_block.evaluate(context) + result = Liquid::Utils.to_liquid_value( + first_block.evaluate(context) + ) + + unless result return first_block.attachment.render_to_output_buffer(context, output) end # After the first condition unless works just like if @blocks[1..-1].each do |block| - if block.evaluate(context) + result = block.evaluate(context) + result = result.to_liquid_value if result.is_a?(Liquid::Drop) + + if result return block.attachment.render_to_output_buffer(context, output) end end diff --git a/lib/liquid/utils.rb b/lib/liquid/utils.rb index 15a513f..38a406e 100644 --- a/lib/liquid/utils.rb +++ b/lib/liquid/utils.rb @@ -81,5 +81,13 @@ module Liquid rescue ::ArgumentError nil end + + def self.to_liquid_value(obj) + # Enable "obj" to represent itself as a primitive value like integer, string, or boolean + return obj.to_liquid_value if obj.respond_to?(:to_liquid_value) + + # Otherwise return the object itself + obj + end end end diff --git a/lib/liquid/variable_lookup.rb b/lib/liquid/variable_lookup.rb index 48c7d98..9d5dba6 100644 --- a/lib/liquid/variable_lookup.rb +++ b/lib/liquid/variable_lookup.rb @@ -40,6 +40,9 @@ module Liquid @lookups.each_index do |i| key = context.evaluate(@lookups[i]) + # Cast "key" to its liquid value to enable it to act as a primitive value + key = Liquid::Utils.to_liquid_value(key) + # If object is a hash- or array-like object we look for the # presence of the key and if its available we return it if object.respond_to?(:[]) && diff --git a/test/integration/variable_test.rb b/test/integration/variable_test.rb index dd34d71..b0b70f8 100644 --- a/test/integration/variable_test.rb +++ b/test/integration/variable_test.rb @@ -15,6 +15,31 @@ class VariableTest < Minitest::Test assert_template_result('foobar', '{{ foo }}', 'foo' => ThingWithToLiquid.new) end + def test_variable_lookup_calls_to_liquid_value + assert_template_result('1', '{{ foo }}', 'foo' => IntegerDrop.new('1')) + assert_template_result('2', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => [1, 2, 3]) + assert_template_result('one', '{{ list[foo] }}', 'foo' => IntegerDrop.new('1'), 'list' => { 1 => 'one' }) + assert_template_result('Yay', '{{ foo }}', 'foo' => BooleanDrop.new(true)) + assert_template_result('YAY', '{{ foo | upcase }}', 'foo' => BooleanDrop.new(true)) + end + + def test_if_tag_calls_to_liquid_value + assert_template_result('one', '{% if foo == 1 %}one{% endif %}', 'foo' => IntegerDrop.new('1')) + assert_template_result('true', '{% if foo == true %}true{% endif %}', 'foo' => BooleanDrop.new(true)) + assert_template_result('true', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(true)) + + assert_template_result('', '{% if foo %}true{% endif %}', 'foo' => BooleanDrop.new(false)) + assert_template_result('', '{% if foo == true %}True{% endif %}', 'foo' => BooleanDrop.new(false)) + end + + def test_unless_tag_calls_to_liquid_value + assert_template_result('', '{% unless foo %}true{% endunless %}', 'foo' => BooleanDrop.new(true)) + end + + def test_case_tag_calls_to_liquid_value + assert_template_result('One', '{% case foo %}{% when 1 %}One{% endcase %}', 'foo' => IntegerDrop.new('1')) + end + def test_simple_with_whitespaces template = Template.parse(%( {{ test }} )) assert_equal(' worked ', template.render!('test' => 'worked')) @@ -104,4 +129,8 @@ class VariableTest < Minitest::Test def test_dynamic_find_var assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar') end + + def test_raw_value_variable + assert_template_result('bar', '{{ [key] }}', 'key' => 'foo', 'foo' => 'bar') + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 5afd10f..f5c1c6a 100755 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -119,6 +119,44 @@ class ThingWithToLiquid end end +class IntegerDrop < Liquid::Drop + def initialize(value) + super() + @value = value.to_i + end + + def ==(other) + @value == other + end + + def to_s + @value.to_s + end + + def to_liquid_value + @value + end +end + +class BooleanDrop < Liquid::Drop + def initialize(value) + super() + @value = value + end + + def ==(other) + @value == other + end + + def to_liquid_value + @value + end + + def to_s + @value ? "Yay" : "Nay" + end +end + class ErrorDrop < Liquid::Drop def standard_error raise Liquid::StandardError, 'standard error'