Ruby Monstas


Embedded Ruby - ERB

Templating

Templates are pre-designed documents, that contain static content and slots for dynamic content.

Email template example

Hi [USERNAME]

Thank you for registering at [PLATFORM_NAME]!
Use this token to confirm your email address
when you sign in for the first time:

[CONFIRMATION_TOKEN]

Have a great day!

The parts surrounded by [] are the slots for dynamic content, the rest is static content

Embedded Ruby

In Ruby we can use Embedded Ruby, or ERB, to design such templates.

ERB Example

require "erb"
name = "Bill"
greeting_template = "Hi <%= name %> 👋"
ERB.new(greeting_template).result(binding) # => Hi Bill 👋

🥵

Interpolation?

Why don't we use String interpolation?

name = "Bill"
"Hi #{name} 👋"         # => Hi Bill 👋

💪

✋ String interpolation gets messy if we have more complex outputs.

Complexity

name = "Bill"

movies = [
  { name: "Groundhog Day", year: 1993 },
  { name: "Lost In Translation", year: 2003 },
  { name: "Moonrise Kingdom", year: 2012 }
]

Target output

Hi Bill 👋

Do you want to watch a movie? Today we have:

* Groundhog Day (1993)
* Lost In Translation (2003)
* Moonrise Kingdom (2012)

- Your Cheap Video Network

...with Interpolation

output = "Hi #{name} 👋\n"

output << "\nDo you want to watch a movie? Today we have:\n\n"

movies.each do |movie|
  output << "* #{movie[:name]} (#{movie[:year]})\n"
end

output << "\n- Your Cheap Video Network\n"

...with ERB

movies_template = %q{
Hi <%= name %>

Do you want to watch a movie? Today we have:

<% movies.each do |movie| %>
* <%= movie[:name] %> (<%= movie[:year] %>)
<% end %>

- Your Cheap Video Network
}
require "erb"
ERB.new(movies_template).result(binding)

Advantages

  • Flexibility
  • Separation of Concerns
  • Reusability

Flexibility

We can use conditionals, loops, and other control structures to generate dynamic content

Flexibility: Example

church_bell_template = %q{
<% hour.times do %>
  DONG 🔔
<% end %>

<% if (6..12).cover?(hour) %>
  Good morning <%= name %>
<% elsif (12..18).cover?(hour) %>
  Good afternoon <%= name %>
<% else %>
  Good day <%= name %>
<% end %>
}

Flexibility: Example

require "erb"
hour = Time.now.hour    # for example 8, at 08:00
name = "Bill"
ERB.new(church_bell_template).result(binding)

Flexibility: Example

  DONG 🔔
  DONG 🔔
  DONG 🔔
  DONG 🔔
  DONG 🔔
  DONG 🔔
  DONG 🔔
  DONG 🔔

  Good morning Bill

Separation of Concerns

We can separate our code into different files, allowing us to focus on our application logic in one file and our presentation logic in another

Application logic

name = "Bill"
lucky_numbers = (1..50).to_a.sample(6)

Presentation logic

File: ./lucky_numbers.txt

Hi <%= name %> 👋

Today your lucky numbers are:

<% lucky_numbers.sort.each do |lucky_number| %>
  * <%= lucky_number %>
<% end %>

Good luck! 🍀

(...this looks very similar to the email example at the beginning, remember?)

Rendering

require "erb"
template = File.read("./lucky_numbers.txt")
ERB.new(template).result(binding)

Output

Hi Bill 👋

Today your lucky numbers are:

  * 10
  * 12
  * 23
  * 33
  * 39
  * 45

Good luck! 🍀

Reusability

ERB templates can be reused across different parts of our application.

HTML + ERB = ❤️

Let's create an HTML template

File ./chores.html

<h1>Hi <%= username %> 👋</h1>

<p>Don't forget to do the following chores today:</p>

<ul>
  <% chores.each do |chore| %>
    <li><%= chore %></li>
  <% end %>
</ul>

Remember, this is the presentation logic

Application logic

username = "Bill"

chores = [
  "Call mom ☎️",
  "Clean the bath 🫧",
  "Walk the dog 🐕",
  "Learn Spanish 🇪🇸"
]

Rendering

require "erb"
template = File.read("./chores.html")
ERB.new(template).result(binding)

HTML Output

<h1>Hi Bill 👋</h1>

<p>Don't forget to do the following chores today:</p>

<ul>
  <li>Call mom ☎️</li>
  <li>Clean the bath 🫧</li>
  <li>Walk the dog 🐕</li>
  <li>Learn Spanish 🇪🇸</li>
</ul>

Additional Resources

Webapps For Beginners: Embedded Ruby

What questions do you have?