variable tutorial template rails lenguaje language ruby jekyll liquid cycle

tutorial - ruby template



Módulo(o falta del mismo) en el motor de plantillas de Ruby Liquid (7)

Estoy trabajando en un sitio Jekyll y estoy intentando generar tres divs de columna anidados en un div de fila. Liquid hace bastante fácil con su filtro de 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 %}

Sin embargo, esto solo funciona realmente cuando hay 3, 6, 9, etc. publicaciones. Cuando el número total de publicaciones no es un múltiplo de tres, <div class="row"> nunca se cierra - el bucle for finaliza antes de que la etiqueta de cierre se pueda enviar como parte del ciclo de close rows .

En Ruby, PHP o cualquier otro idioma, podría solucionarlo fácilmente con un operador de módulo, por lo que además de close rows ciclo de las close rows , mostraría </div> cuando if site.categories.size % 3 == 0 . Sin embargo, Liquid, porque es un lenguaje de creación de plantillas seguro, no es compatible con el módulo.

¿Qué más puedo hacer para cerrar correctamente <div class="row"> cuando el número total de publicaciones no es un múltiplo de tres?


Aprendí mucho de esta publicación, y estos son los tres patrones que usé a lo largo de mi proyecto. Funcionó muy bien con Bootstrap también. Solo cambia la clase de columna en el siguiente código. En lugar de columnas, se pueden aplicar los mismos patrones a otros escenarios donde el módulo es útil, como filas impares. Espero que ayude a alguien -

Cuatro columnas:

<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>

Tres columnas:

<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>

Dos columnas:

<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>


He encontrado esta manera de trabajar muy bien!

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


IIRC Liquid no bloquea la operación de módulo, solo el carácter % . Puede realizar un módulo sin utilizar el operador % . Por ejemplo, 14.modulo(3) => 2 lugar de 14 % 3 .


La única forma por ahora es escribir un filtro de líquido para lograr esto. Registre el filtro en algún lugar de su código donde sea apropiado (está en diferentes lugares si se usa con rieles y sin ellos).

Liquid :: Template.register_filter (LiquidFilters)

En tu directorio de proyectos / lib agrega liquid_filters.rb:

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

Después de eso puedes usarlo como sigue en tus plantillas: {{variable | mod: 5}}

Y si necesita usarlo para alguna lógica, puede capturar el valor.

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

Simplemente me he dado cuenta de que el valor capturado es una cadena, por lo que para poder compararla se usa

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


Me doy cuenta de que la pregunta se resolvió para el autor de la pregunta, pero hace poco me encontré con este tipo de situación en Liquid y pensé en proporcionar mi solución en caso de que ayudara a alguien con requisitos de marcado similares.

En mi caso, ya pasé una instrucción if que verifica que hay al menos una publicación, así que creé la primera división de "fila" fuera del bucle. También lo cierro después del bucle for. Esto protege contra un caso donde hay menos de tres puestos.

<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>

Después de cada tres publicaciones, el ciclo cerrará la fila actual y abrirá una nueva, a unless la publicación fuera la última en el forloop, en cuyo caso no queremos abrir una nueva fila y dejar que el ajuste </div> ciérralo


Para su ejemplo específico, podría usar {% cycle ''close rows'': nil, ''</div>'', ''</div>'' %} después de {% endfor %} .


Utilicé otro truco en un bucle for: inútil en su caso, útil si solo desea un módulo para averiguar si su línea ha terminado y necesita una nueva fila, como hice yo.

En este ejemplo iré con una línea de 4 artículos:

{% 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

No muy agradable, pero fácil.