Ruby的液体模板引擎中的模数(或缺少模数)

时间:2010-02-11 16:40:16

标签: ruby jekyll liquid cycle

我正在研究一个Jekyll网站,我正在尝试输出嵌套在行div中的三个列div。 Liquid使用cycle过滤器可以轻松实现这一目标:

{% for p in site.categories.post %}
    {% cycle 'add rows': '<div class="row">', nil, nil %}
        <div class="column">
            <a href="{{ p.url }}">{{ p.title }}</a>
        </div>
    {% cycle 'close rows': nil, nil, '</div>' %}
{% endfor %}

然而,只有当有3个,6个,9个等帖子时,这才真正有用。当帖子总数不是三的倍数时,<div class="row">永远不会关闭 - for循环在结束标记可以作为close rows周期的一部分输出之前结束。

在Ruby,PHP或任何其他语言中,我可以使用模运算符轻松解决此问题,因此除close rows周期外,我会在</div>时输出if site.categories.size % 3 == 0。但是,Liquid,因为它是一种安全的模板语言,不支持模数。

当帖子总数不是三的倍数时,我还能做些什么才能正确关闭<div class="row">

7 个答案:

答案 0 :(得分:13)

对于您的具体示例,您可以在{% cycle 'close rows': nil, '</div>', '</div>' %}之后使用{% endfor %}

答案 1 :(得分:13)

我发现这种方式很棒!

{% assign mod = forloop.index0 | modulo:4 %}
{% if mod == 0 %}
   <!-- Do stuff -->
{% endif %}

答案 2 :(得分:8)

现在唯一的方法就是写一个液体过滤器来完成这个任务。在适当的代码中的某处注册过滤器(如果使用rails而不使用它们,则在不同的地方注册)。

  

液体:: Template.register_filter(LiquidFilters)

在你的项目/ lib目录中添加liquid_filters.rb:

module LiquidFilters  
  # makes modulus operation available to templates
  def mod(data, param)
    data % param
  end  
end

之后,您可以像在模板中一样使用它: {{变量| mod:5}}

如果您需要将它用于某些逻辑,您可以捕获该值。

{% capture modulus %}{{ variable | mod:5 }}{% endcapture %}

我刚注意到捕获的值是一个字符串,所以为了比较你使用

{% if modulus == "0" %}
 ..
{% endif %}

答案 3 :(得分:3)

我在for循环中使用了另一个技巧:在你的情况下没用,如果你只想要一个模数以便找出你的行已经结束并且你需要一个新行,就像我一样。

在这个例子中,我将使用4行项目:

{% assign currentRow = 1 %}
# enter the for loop ... then, with 4 as the divisor:
{% if forloop.index == 4 * currentRow %}
  # do whatever you want
  {% assign currentRow = currentRow + 1 %}
{% endif %}
# exit the for loop

不是很好,但很容易。

答案 4 :(得分:3)

我意识到这个问题已经解决了问题,但我最近遇到了Liquid的这种情况,并且认为我会提供我的解决方案,以防它有助于有类似标记要求的人。

在我的情况下,我已经传递了一个if语句来验证至少有一个帖子,所以我在循环外创建了第一个“row”div。我也在for循环后关闭它。这可以防止帖子少于三个的情况。

<div class="row">

    {% for p in posts %}
        <div class="column">
            <!-- Post code here -->
        </div>
        {% unless forloop.last %}
            {% cycle '', '', '</div><div class="row">' %}
        {% endunless %}
    {% endfor %}

</div>

每三个帖子之后,循环将关闭当前行并打开一个新的unless帖子是forloop中的最后一个,在这种情况下我们不想打开新行,并且让包裹</div>关闭它。

答案 5 :(得分:2)

我从这篇文章中学到了很多东西,这是我在整个项目中使用的三种模式。它也适用于Bootstrap。只需更改以下代码中的列类即可。可以将相同的模式应用于模数有用的其他方案,例如奇偶行,而不是列。希望它可以帮助某人 -

四栏:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>', '</div>' %}
</div>

三栏:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil, nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>', '</div>' %}
</div>

两栏:

<div class="container">
    {% for post in site.posts %}
        {% cycle 'add row' : '<div class="row">', nil %}
            <div class="column">
                <!-- liquid tags here -->
            </div>
        {% cycle 'end row' : nil, '</div>' %}
    {% endfor %}
    {% cycle 'end row' : nil, '</div>' %}
</div>

答案 6 :(得分:1)

IIRC Liquid不会阻止模运算,只会阻止%个字符。您可以在不使用%运算符的情况下执行模数。例如,14.modulo(3) => 2代替14 % 3