Views & ERB
📝 Views & ERB
🧬 ERB Tags — <%= %> vs <% %>
ERB vs EJS — A Genuine Syntax Convergence
| Purpose | EJS (Express) | ERB (Rails) |
|---|---|---|
| Output a value (escaped) | <%= value %> | <%= value %> |
| Run logic, no output | <% if (x) { %> | <% if x %> |
| File extension | .ejs | .html.erb |
This is worth pausing on: <%= %> for output and <% %> for logic-only is identical syntax between EJS and ERB — a genuine convergence, similar in spirit to the spaceship operator and safe navigation operator syntax Ruby Course 2 flagged converging into PHP. The main practical difference: ERB's logic tags use Ruby's own if/end block syntax (Ruby Course 1, Chapter 3) instead of EJS's JavaScript curly braces.
🌉 Instance Variables Arrive Automatically
Recall Chapter 3's @post — every instance variable set in a controller action is automatically available inside that action's view, with no explicit data-passing step. Compare this to Express, where res.render("show", { post }) requires the controller to explicitly build and pass a data object into the template every single time.
🖼️ Layouts
yield here is the same keyword from Ruby Course 1 Chapter 4's blocks — the layout is, in effect, a method that yields to whichever view is currently being rendered. Every view in the app is automatically wrapped in application.html.erb with zero effort on the individual view's part.
Express's EJS setup (Chapter 1's comparisons already flagged this pattern) typically requires each template to explicitly <%- include('partials/header') %> and <%- include('partials/footer') %> itself — shared page structure is opt-in, template by template. Rails' layout wraps every view automatically; you'd have to explicitly opt out (layout false) rather than opt in.
🧩 Partials
Partials are reusable view fragments, named with a leading underscore on disk but referenced without it. render "form", post: @post passes post in explicitly as a local variable to the partial — this is the conceptual equivalent of EJS's include(), just with Rails' own naming convention (the underscore) marking a file as a partial rather than a full view.
🛠️ View Helpers
link_to is a real Ruby method call — using the named route helpers from Chapter 2 — that generates the HTML for you, rather than hand-writing an <a href="..."> tag with a string-interpolated URL the way an EJS template typically would. Dozens of similar helpers exist for forms, dates, and more.
🛡️ Automatic Escaping
<%= %> automatically HTML-escapes its output by default — the exact XSS protection covered in depth in the completed XSS security course, here built into the templating layer itself rather than something you have to remember to apply. EJS's <%= %> auto-escapes too (a real parallel), while EJS's separate <%- %> tag opts out; Rails instead keeps one output tag and requires an explicit raw(...) call (or .html_safe) to bypass escaping.
📜 Templating, Side by Side
EJS vs ERB
| Concept | EJS (Express) | ERB (Rails) |
|---|---|---|
| Passing data in | Explicit object in res.render(view, data) | Automatic — controller's instance variables |
| Shared layout | Opt-in via include() in each template | Automatic — every view wraps in the layout by default |
| Reusable fragment | include('partials/name') | render "name", locals passed explicitly |
| Escape by default? | Yes, with <%= %> (opt out via <%- %>) | Yes, with <%= %> (opt out via raw()/.html_safe) |
💻 Coding Challenges
Challenge 1: An index View
Write app/views/posts/index.html.erb that loops over @posts (an array of Post objects, each with .title and .published?) using <% %>, and for each one outputs the title with <%= %>, only showing a "Published" label next to posts where .published? is true.
Goal: Practice correctly distinguishing output tags from logic-only tags in a realistic loop.
Challenge 2: A Shared Navbar Partial
Write a partial app/views/shared/_navbar.html.erb containing a simple nav with two link_to calls, then show the single line you'd add to application.html.erb (above the yield) to render it on every page.
Goal: Practice the underscore-on-disk, no-underscore-when-referenced partial convention.
Challenge 3: Escaping vs raw
Given @bio = "Bold claim" set in a controller, write two lines in a view: one using plain <%= %> and one using raw(...). Add a comment describing exactly how each would actually render in the browser, and which one you'd use for genuinely untrusted, user-submitted content.
Goal: Be certain, not just aware, of when escaping matters.
The XSS course already covered why unescaped user content is dangerous. What's worth noticing here is the framework-level design choice: Rails makes the safe behavior (<%= %>, escaped) the default and the dangerous behavior (raw(...)) something you have to explicitly, visibly opt into. That's a meaningfully different security posture than a templating setup where escaping is something a developer has to remember to apply correctly every time.
🎯 What's Next
Next chapter: Active Record Basics — migrations, models, and how Post.find(params[:id]), used casually throughout this chapter and the last, actually talks to the database.