Class: Liquid::For

Inherits:
Block show all
Defined in:
lib/liquid/tags/for.rb

Overview

“For” iterates over an array or collection. Several useful variables are available to you within the loop.

Basic usage:

{% for item in collection %}
  {{ forloop.index }}: {{ item.name }}
{% endfor %}

Advanced usage:

{% for item in collection %}
  <div {% if forloop.first %}class="first"{% endif %}>
    Item {{ forloop.index }}: {{ item.name }}
  </div>
{% endfor %}

You can also define a limit and offset much like SQL. Remember that offset starts at 0 for the first item.

  {% for item in collection limit:5 offset:10 %}
    {{ item.name }}
  {% end %}             

To reverse the for loop simply use {% for item in collection reversed %}

Available variables:

forloop.name

‘item-collection’

forloop.length

Length of the loop

forloop.index

The current item’s position in the collection; forloop.index starts at 1. This is helpful for non-programmers who start believe the first item in an array is 1, not 0.

forloop.index0

The current item’s position in the collection where the first item is 0

forloop.rindex

Number of items remaining in the loop (length - index) where 1 is the last item.

forloop.rindex0

Number of items remaining in the loop 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.

Constant Summary collapse

Syntax =
/(\w+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/

Constants inherited from Block

Block::ContentOfVariable, Block::FullToken, Block::IsTag, Block::IsVariable

Instance Attribute Summary

Attributes inherited from Tag

#nodelist

Instance Method Summary collapse

Methods inherited from Block

#block_delimiter, #block_name, #create_variable, #end_tag, #parse, #unknown_tag

Methods inherited from Tag

#name, #parse

Constructor Details

#initialize(tag_name, markup, tokens) ⇒ For

Returns a new instance of For.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/liquid/tags/for.rb', line 47

def initialize(tag_name, markup, tokens)
  if markup =~ Syntax
    @variable_name = $1
    @collection_name = $2
    @name = "#{$1}-#{$2}"           
    @reversed = $3             
    @attributes = {}
    markup.scan(TagAttributes) do |key, value|
      @attributes[key] = value
    end        
  else
    raise SyntaxError.new("Syntax Error in 'for loop' - Valid syntax: for [item] in [collection]")
  end

  super
end

Instance Method Details

#render(context) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/liquid/tags/for.rb', line 64

def render(context)        
  context.registers[:for] ||= Hash.new(0)

  collection = context[@collection_name]
  collection = collection.to_a if collection.is_a?(Range)

  return '' unless collection.respond_to?(:each) 
                                             
  from = if @attributes['offset'] == 'continue'
    context.registers[:for][@name].to_i
  else
    context[@attributes['offset']].to_i
  end
    
  limit = context[@attributes['limit']]
  to    = limit ? limit.to_i + from : nil  
      
                   
  segment = slice_collection_using_each(collection, from, to)      
  
  return '' if segment.empty?
  
  segment.reverse! if @reversed

  result = []
    
  length = segment.length            
        
  # Store our progress through the collection for the continue flag
  context.registers[:for][@name] = from + segment.length
          
  context.stack do 
    segment.each_with_index do |item, index|     
      context[@variable_name] = item
      context['forloop'] = {
        'name'    => @name,
        'length'  => length,
        'index'   => index + 1, 
        'index0'  => index, 
        'rindex'  => length - index,
        'rindex0' => length - index -1,
        'first'   => (index == 0),
        'last'    => (index == length - 1) }

      result << render_all(@nodelist, context)
    end
  end
  result     
end

#slice_collection_using_each(collection, from, to) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/liquid/tags/for.rb', line 114

def slice_collection_using_each(collection, from, to)       
  segments = []      
  index = 0      
  yielded = 0
  collection.each do |item|         
            
    if to && to <= index
      break
    end
    
    if from <= index                               
      segments << item
    end                    
            
    index += 1
  end    

  segments
end