From 205bd19d3fa6b2f2bef717ac71aaa09667b0975e Mon Sep 17 00:00:00 2001 From: Justin Li Date: Wed, 4 Feb 2015 12:43:09 -0500 Subject: [PATCH] Add forloop.parentloop as a reference to the parent loop --- lib/liquid/tags/for.rb | 20 ++++++++++++-------- test/integration/tags/for_tag_test.rb | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/liquid/tags/for.rb b/lib/liquid/tags/for.rb index 31da9d6..33f12af 100644 --- a/lib/liquid/tags/for.rb +++ b/lib/liquid/tags/for.rb @@ -42,6 +42,7 @@ module Liquid # where 0 is the last item. # forloop.first:: Returns true if the item is the first item. # forloop.last:: Returns true if the item is the last item. + # forloop.parentloop:: Provides access to the parent loop, if present. # class For < Block Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o @@ -98,18 +99,21 @@ module Liquid # Store our progress through the collection for the continue flag context.registers[:for][@name] = from + segment.length + parent_loop = context['forloop'.freeze] + context.stack do segment.each_with_index do |item, index| context[@variable_name] = item context['forloop'.freeze] = { - 'name'.freeze => @name, - 'length'.freeze => length, - 'index'.freeze => index + 1, - 'index0'.freeze => index, - 'rindex'.freeze => length - index, - 'rindex0'.freeze => length - index - 1, - 'first'.freeze => (index == 0), - 'last'.freeze => (index == length - 1) + 'name'.freeze => @name, + 'length'.freeze => length, + 'index'.freeze => index + 1, + 'index0'.freeze => index, + 'rindex'.freeze => length - index, + 'rindex0'.freeze => length - index - 1, + 'first'.freeze => (index == 0), + 'last'.freeze => (index == length - 1), + 'parentloop'.freeze => parent_loop } result << @for_block.render(context) diff --git a/test/integration/tags/for_tag_test.rb b/test/integration/tags/for_tag_test.rb index 8ccc056..23752bb 100644 --- a/test/integration/tags/for_tag_test.rb +++ b/test/integration/tags/for_tag_test.rb @@ -298,6 +298,22 @@ HERE 'string' => "test string") end + def test_for_parentloop_references_parent_loop + assert_template_result('1.1 1.2 1.3 2.1 2.2 2.3 ', + '{% for inner in outer %}{% for k in inner %}' + + '{{ forloop.parentloop.index }}.{{ forloop.index }} ' + + '{% endfor %}{% endfor %}', + 'outer' => [[1, 1, 1], [1, 1, 1]]) + end + + def test_for_parentloop_nil_when_not_present + assert_template_result('.1 .2 ', + '{% for inner in outer %}' + + '{{ forloop.parentloop.index }}.{{ forloop.index }} ' + + '{% endfor %}', + 'outer' => [[1, 1, 1], [1, 1, 1]]) + end + def test_blank_string_not_iterable assert_template_result('', "{% for char in characters %}I WILL NOT BE OUTPUT{% endfor %}", 'characters' => '') end