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 =
/\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o

Constants inherited from Block

Block::ContentOfVariable, Block::FullToken, Block::TAGSTART, Block::VARSTART

Instance Attribute Summary

Attributes inherited from Tag

#line_number, #options, #warnings

Instance Method Summary collapse

Methods inherited from Block

#blank?, #block_delimiter, #block_name, #create_variable, #parse, #render_token_with_profiling, #warnings

Methods inherited from Tag

#blank?, #name, #parse, parse, #raw

Methods included from ParserSwitching

#parse_with_selected_parser

Constructor Details

#initialize(tag_name, markup, options) ⇒ For

Returns a new instance of For.



49
50
51
52
53
# File 'lib/liquid/tags/for.rb', line 49

def initialize(tag_name, markup, options)
  super
  parse_with_selected_parser(markup)
  @nodelist = @for_block = []
end

Instance Method Details

#nodelistObject



55
56
57
58
59
60
61
# File 'lib/liquid/tags/for.rb', line 55

def nodelist
  if @else_block
    @for_block + @else_block
  else
    @for_block
  end
end

#render(context) ⇒ Object



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

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'.freeze] == 'continue'.freeze
    context.registers[:for][@name].to_i
  else
    context[@attributes['offset'.freeze]].to_i
  end

  limit = context[@attributes['limit'.freeze]]
  to    = limit ? limit.to_i + from : nil

  segment = Utils.slice_collection(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'.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)
      }

      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



63
64
65
66
# File 'lib/liquid/tags/for.rb', line 63

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