
Your comprehensive guide for Twig front-end view templates.
Last Updated

Read more
This post is an iteration on ERB and Twig Cross-Reference for Front-End Development. That post is geared towards developers who want to translate their Twig knowledge to ERB, or vice versa. You may also be interested in Fundamental Twig for Front-End Development.
ERB (Embedded Ruby) is a feature of Ruby that lets you —you guessed it!— embed Ruby in other files. ERB files have the extension .<compiled_extension>.erb. It is the language HAML and Slim are shorthand for. ERB is commonly used for templating Views in Rails apps.
Because it can do anything Ruby can do, it’s extremely powerful, has a steeper learning curve than languages intended for front-end templates specifically, and can do a lot that isn’t relevant to front-end templating. There’s no cannonical ERB-for-front-end-developers documentation, and the Rails official documentation is immense and hard to dig through. Some resources if for learning ERB:
link... and button_to methods are essential.content tag and tag methods are useful.link_to<%# … %>
<%# comment %>=begin…=end
the opening and closing tags must be at the start of the line
<%
=begin %>
block comment
(both lines of both the begin and end tags must be at the start of their lines)
<%
=end %>not
<%
=begin %>
not a comment
<%
=end %><%= … %>
<%= "print this" %> <%# output: `"print this"` %>
<%= 1 + 2 %> <%# output: `3` %><% … %>
<% if … do %> … <% end %>if and unless
<%= 2 if true %> <%# output: `2` %>
<%= 2 if false %> <%# output: `nil` %>
<%= 2 unless true %> <%# output: `nil` %>
<%= 2 unless false %> <%# output: `2` %>if…elsif…end
<%# assuming x, y, z, and n are defined %>
<% if x %>
y
<% elsif z == n %> <%# note the spelling of elsif %>
0
<% else %>
1
<% end %>ERB supports “condition ? iftrue : iffalse”, and “ifselftrue ?: otherwise”.
Note that the “then” case : must be provided
<%# assuming x, y, z, and n are defined %>
<%# if x then y %>
<%# omitting the "else" will throw an error #>
<%= x ? y : '' %>
<%# if x is true, y. otherwise, if z equals n then 0. otherwise 1 %>
<%= x ? y : z == n ? 0 : 1 %>
<%# ternary operator: x if x is true, otherwise y %>
<%= x ?: y %>0 is True in Boolean contexts
<%= false ? 'truthy' : 'falsy' %> <%# output: `"falsy"` %>
<%= 0 ? 'truthy' : 'falsy' %> <%# output: `"truthy"` %>=
<% var = 1 %>
<% anotherVar = 0 %>
<% falseVar = false %>
<%= 2 if var %> <%# output: `2` %>
<%= 2 if anotherVar %> <%# output: `2` %>
<%= 2 if falseVar %> <%# output: `` %>
<%= 2 unless falseVar %> <%# output: `2` %>Multi-line blocks of markup can stored in an identifier with content_for x do…end
<% content_for longVar do %>
<div>
…
</div>
<% end %>
<%= content_for(longVar) %>Note: content_for is additive: each time you provide content for a given variable, that content is appeneded to what was there already. To use content_for to overwrite a global variable, use the flush: true option:
<% content_for refreshedVar do %>
a
<% end %>
<% content_for refreshedVar, flush: true do %>
b
<% end %>defined?()
<%# output: the content if `var` is defined %>
<% if defined?(var) %>
…
<% end %>
<%# output: `var` if `var` is defined, otherwise `fallback` %>
<%= defined?(var) ? var : fallback %>||=, the OR Equal operator
<%# output: `var` if it is defined and not nil and not false, otherwise `fallback` %>
<% var ||= fallback %>
<%
=begin %> common front-end use cases:
1. output a variable only if it is defined
<%
=end %>
<% var ||= nil %>
<%# set a variable with a fallback %>
<% x = y ||= nil %>#{var}
<% x = 1 %>
<%= "this is interpolated: #{x}" %><%# output: `this is interpolated: 1` %>+ (plus). Note that to concatenate a string and a number in Ruby, the number must be converted to a string.
<% string_variable = 'world' %>
<% number_variable = 2 %>
<%= 'hello ' + string_variable %> <%# output: `"hello world"` %>
<%= "example #{number_variable}" %> <%# output: `"example 2"` %>
<%= 'example ' + 3.to_s %> <%# output: `"example 3"` %>n.each do |i|…end
<% items = ['a', 'b', 'c'] %>
<%# output: `...` %>
<% [0..items.length].each do %>.<% end %>
<%# output: `a b c ` %>
<% items.each do |item| %>
<%= item %>
<% end %>n.each_with_index do |i, index|…end
<%# output: `0. a 1. b 2. c ` %>
<% items = ['a', 'b', 'c'] %>
<% items.each_with_index do |item,index| %>
<%= index %>. <%= item %>
<% end %>n.times do |i|…end
<%# output: `0 1 2 3 4 5 6 7 8 9` %>
<% 10.times do |i| %><%= i %> <% end %>.each_with_index’s index is always 0-indexed, so add 1
<% items.each_with_index do |item,index| %>
<%= index + 1 %>. <%= item %>
<% end %>n.times do |i|…end
<%# output: `1 2 3 4 5 6 7 8 9 10 ` %>
<% 10.times do |i| %><%= i %> <% end %>n.times do |i|…end
<% n = 3 %>
<%# output: `...` %>
<% n.times do %>.<% end %>
<%# output: `1 2 3 ` %>
<% n.times do |i| %>
<%= i %>
<% end %>There are several options for formatting an object’s data, notably: simply outputting, .inspecting, and debug()ing. For basic data-checking purposes in a view, the essential difference is debug() returns YAML while inspect and printing return strings.
<%# for some object `posts` %>
<%= posts %>
<%= posts.inspect %>
<%= debug(posts) %>.slice(index), .slice(start,count)
<%= [1,2,3,4].slice(1) %> <%# output: `2` %>
<%= [1,2,3,4].slice(1,2) %> <%# output: `[2,3]` %>count items.take(count) or .first(count)
<%= [1,2,3,4].take(2) %> <%# output: `[1,2]` %>
<%= [1,2,3,4].first(2) %> <%# output: `[1,2]` %>If trim_mode is set to -, a - in the closing erb tag will trim trailing whitespace:
<% something -%>
1
<%= something_else -%>
2
<% another_thing %>is equivalent to
<% something %>1
<%= something_else %>2
<% another_thing %>Use a Symbol :property to look up an operation on a Hash:
<% myHash = {hello: 'world'} %>
<%= myHash[:hello] %> <%# output: "world" %>For a layout file that pulls in page: content_for in child, yield in parent
layouts/layout.html.erb
<%= yield :myBlock %>views/page.html.erb
<% content_for :myBlock do %>
the content
<% end %>layouts/layout.html.erb
<% if content_for?(:my_content) %>
<%= yield :my_content %>
<% else %>
default content
<% end %>views/page.html.erb
<% content_for :my_content do %>
the content
<% end %>render will output the contents of another file
<%= render 'path/to/x' %>To pass values to the rendered file, define them:
<% a = 1 %>
<% b = 2 %>
<%= render 'path/to/x', a:a, b:b %> <%# in path/to/x a=1 and b=2 %>If the rendered file expects different variable names, use those:
<% a = 1 %>
<% b = 2 %>
<%= render 'path/to/x', y:a, z:b %> <%# in path/to/x y=1 and z=2 %>
Fundamental Twig for Front-End Development
Your comprehensive guide for Twig front-end view templates.

Accessible CSS-Only Light/Dark Toggles (with JS persistence as progressive enhancement)
CSS’s :has() can obviate JS

Tools, Services, & Office Equipment I Use
Preferences preferences preferences