Lesson 3 — Text, whitespace, and the difference from ERB
How text gets into the output
In Phlex, text content is output by returning a string from an element’s block:
|
|
This works because Phlex uses the block’s return value as the element’s text content — but only under a specific condition. The official Phlex documentation states it precisely:
“If the return value of the block is a String, Symbol, Integer or Float and no output methods were used, the return value will be output as text.”
That qualifying clause — and no output methods were used — is the most important thing to understand about text output in Phlex. Everything else follows from it.
What “no output methods were used” means in practice
The moment a tag method call appears inside a block, the return value mechanism is bypassed entirely. Only explicit output method calls produce output. Bare strings — even as the last expression — are silently discarded.
This is a common source of confusion. Here is what happens when you try to mix bare strings with tag method calls:
|
|
Both strings are lost. The a tag method outputs directly to the buffer and returns nil. Since an output method was used inside the block, Phlex ignores the block’s return value entirely — only what was explicitly written to the buffer appears in the output.
This is a significant difference from ERB, where <%= "Visit " %> would output that string regardless of what else appeared around it.
plain — explicit text output
plain is the solution. It writes text directly to the output buffer immediately, regardless of its position in the block:
|
|
Each plain call writes its text to the buffer immediately and in order. The output is exactly what you would expect.
When to use plain and when not to
Use plain whenever:
- You need text before or between elements inside a block
- The block contains any tag method call and you need text output
- You are building text from logic and want to be explicit about what is output
For a simple element containing only text, the block return value is fine and plain is unnecessary:
|
|
Reserve plain for cases where output methods are also present in the block.
A realistic example
Here is a byline paragraph that requires plain — it cannot be built correctly using block return values alone:
|
|
Output:
|
|
Without plain, "Written by " and " on 30 March 2025 · " would both be silently discarded because strong and span are output methods.
Whitespace
Phlex produces compact HTML with no extra whitespace between elements:
|
|
No spaces between the spans. For inline elements where text flow requires a space, be explicit with plain:
|
|
In practice, use CSS for spacing between elements rather than injecting whitespace characters — it is more maintainable and avoids unexpected layout behaviour.
The whitespace helper
For cases where you genuinely need a whitespace character in the output, Phlex provides whitespace as a cleaner alternative to plain " ":
|
|
Use whitespace when the sole purpose is adding a single space between inline elements. Use plain { " " } when the space is part of a larger string construction — plain { ", " } for example — to keep the intent consistent.
whitespace also accepts a block, in which case a space is output on both sides of the block’s content:
|
|
String interpolation
String interpolation works naturally inside any text-producing block:
|
|
There is nothing special to learn here — it is just Ruby string interpolation. The contrast with ERB is worth noting though. In ERB you would write:
<h1>Good <%= @time_of_day %>, <%= @name %>!</h1>Mixing two syntaxes inside one element. In Phlex it is one Ruby string with normal interpolation — no context switching.
Where things get more interesting is combining interpolation with plain for multi-part text. Because it is all Ruby, any expression works inside the interpolation — ternaries, method calls, formatting — without reaching for a helper:
|
|
Helper methods for sub-templates
Because view_template is a plain Ruby method, you can extract parts of it into private helper methods. This is the idiomatic way to break up a large template without creating separate component files:
|
|
Output:
|
|
Private helper methods are the natural way to decompose a complex view_template without the overhead of separate component classes. Use them freely — they are just Ruby methods.
ERB vs Phlex: the mental model shift
In ERB the template is a string with Ruby interpolated into it. The default mode is “output everything”, and you opt in to Ruby with <% %> and <%= %>:
<p>
Written by <%= @author %> on <%= @date %>
</p>In Phlex the default mode is “execute Ruby”, and you explicitly opt in to output with method calls — tag methods, plain, and render. Nothing is output unless you call a method that outputs it. The block return value is a convenience shortcut that only applies when no output methods are present.
This distinction has a practical consequence: in ERB it is easy to accidentally output nothing (used <% rather than <%= …), output too much (stray return value), or create invisible whitespace. In Phlex, if something appears in the output, you put it there deliberately.
Exercise
Create 03_exercise.rb. Build a ProseComponent that renders an article with:
- A heading
- A byline built from multiple parts:
"By ", then a<strong>with the author name, then" · ", then the date — all inside a single<p>tag - Two body paragraphs passed in as an array
For example, calling it like this:
|
|
Should produce:
|
|
The byline <p> cannot be built correctly using block return values alone — you must use plain. The body paragraphs can be rendered with a simple each loop.
Solution for Exercise 03
|
|