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>
{% else %}
  There is nothing in the collection.
{% 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)?/o

Constants inherited from Block

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

Instance Attribute Summary

Attributes inherited from Tag

#context, #nodelist

Instance Method Summary collapse

Methods inherited from Block

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

Methods inherited from Tag

#name, #parse

Constructor Details

#initialize(tag_name, markup, tokens, context) ⇒ For

Returns a new instance of For.



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

def initialize(tag_name, markup, tokens, context)
  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

  @nodelist = @for_block = []
  super
end

Instance Method Details

#render(context) ⇒ Object



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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/liquid/tags/for.rb', line 72

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

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

  # Maintains Ruby 1.8.7 String#each behaviour on 1.9
  return render_else(context) unless iterable?(collection)

  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 = Utils.slice_collection_using_each(collection, from, to)

  return render_else(context) 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(@for_block, context)

      # Handle any interrupts if they exist.
      if context.has_interrupt?
        interrupt = context.pop_interrupt
        break if interrupt.is_a? BreakInterrupt
        next if interrupt.is_a? ContinueInterrupt
      end
    end
  end
  result
end

#unknown_tag(tag, markup, tokens) ⇒ Object



67
68
69
70
# File 'lib/liquid/tags/for.rb', line 67

def unknown_tag(tag, markup, tokens)
  return super unless tag == 'else'
  @nodelist = @else_block = []
end