If you like highly abstracted view code, you’ll appreciate how concise you can express HTML with Phlex. This snippet renders an HTML table of students in an app I built to manage my local school’s science fair.
class Index < View
# This is rendered for an `<h1>` on this views layout, which
# is not related to the table.
def title = "Students"
def view_template
# Calls the `Table` method with `Student.all` set to `@students`.
# It ultimately renders a `<table>` tag.
Table @students do
# `it` is the table. We call `column` with the argument `"Student"`
# which is set in the `table > thead > th` element.
it.column("Student") { show(it, &:name) }
# The `show` method is a link helper that links to the `Teacher` model,
# which is the same as `url_for(teacher)` in Rails.
it.column("Teacher") { show(it.teacher, &:last_name) }
# The second argument `&:name` calls it.parent.name.
it.column("Parent") { show(it.parent, &:name) }
it.column("Project") { show(it.project, &:title) }
it.column("Registered at") { local_time it.created_at }
# The contents of the link can be changed by returning a value from a block.
it.column("Interview") do |student|
show(student.interview) { interview_name(student.interview) }
end
end
end
end
Here’s the HTML it renders:
<table class="table">
<thead>
<tr>
<th>Student</th>
<th>Teacher</th>
<th>Parent</th>
<th>Project</th>
<th>Registered at</th>
<th>Interview</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="/administrator/students/10">Jenkins McDoogleson</a></td>
<td><a href="/administrator/teachers/5">Flenderson</a></td>
<td><a href="/administrator/parents/3">Sofia McDoogleson</a></td>
<td><a href="/administrator/projects/8">Solar Energy for Schools</a></td>
<td>
<time datetime="2025-02-01T14:30:00Z"
data-local="time"
data-format="%B %e, %Y %l:%M%P"
title="February 1, 2025 at 6:30am PST"
data-processed-at="2025-06-11T06:44:58.841Z"
data-localized="">
February 1, 2025 6:30am
</time>
</td>
<td>
<a href="/administrator/interviews/101">
Barny Blathersmath at
<time datetime="2025-03-28T15:45:00Z"
data-local="time"
data-format="%H:%M"
title="March 28, 2025 at 8:45am PDT"
data-processed-at="2025-06-11T06:44:58.842Z"
data-localized="">
08:45
</time>
</a>
</td>
</tr>
</tbody>
</table>
You don’t have to push Phlex this far, but the point is that since its just Ruby, you could if you want.
A less abstracted Phlex table view might look like this:
class Index < View
def view_template
# Calls the `table` tag on Phlex using `@students`.
table class: "table" do
thead do
tr do
th { "Student" }
th { "Teacher" }
th { "Parent" }
th { "Project" }
th { "Registered at" }
th { "Interview" }
end
end
tbody do
@students.each do |student|
tr do
td { show(student, &:name) }
td { show(student.teacher, &:last_name) }
td { show(student.parent, &:name) }
td { show(student.project, &:title) }
td { local_time student.created_at }
td do
show(student.interview) do
interview_name(student.interview)
text " at "
local_time student.interview.scheduled_at, format: "%H:%M"
end
end
end
end
end
end
end
end
But who wants to type all that?
I’m still playing around with higher levels of abstraction in the Superview and Superlink libraries and I’ll touch on them in my Phlex on Rails video course.