Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Phlex: HTML in Pure Ruby

Phlex: HTML in Pure Ruby

A 30-minute talk with a smidge of live coding to introduce people to the Phlex Ruby library for writing HTML views.

https://github.com/soulcutter/phlex-talk
https://www.phlex.fun/

Bradley Schaefer

September 01, 2023
Tweet

More Decks by Bradley Schaefer

Other Decks in Programming

Transcript

  1. Expectations • This talk is for Web Developers • You

    are familiar with Ruby • My presentation skills could use some work
  2. What is the purpose of this talk? * maybe to

    convince you to start using phlex for everything Adventure! Exploration! Wonder! Fun! Excitement! Joy!
  3. How are you writing HTML templates today? ERB (Embedded RuBy)

    <html> <head><title>Ruby Toys -- <%= @name %></title></head> <body> <h1><%= @name %> (<%= @code %>)</h1> <p><%= @desc %></p> <ul> <% @features.each do |f| %> <li><b><%= f %></b></li> <% end %> </ul> <p> <% if @cost < 10 %> <b>Only <%= @cost %>!!!</b> <% else %> Call for a price, today! <% end %> </p> </body> </html>
  4. How are you writing HTML templates today? ERB (Embedded RuBy)

    Haml (HTML Abstraction Markup Language) <html> <head><title>Ruby Toys -- <%= @name %></title></head> <body> <h1><%= @name %> (<%= @code %>)</h1> <p><%= @desc %></p> <ul> <% @features.each do |f| %> <li><b><%= f %></b></li> <% end %> </ul> <p> <% if @cost < 10 %> <b>Only <%= @cost %>!!!</b> <% else %> Call for a price, today! <% end %> </p> </body> </html> %html %head %title Ruby Toys -- #{@name} %body %h1 #{@name} (#{@code}) %p= @desc %ul - @features.each do |f| %li %b= f %p - if @cost < 10 %b Only #{@cost}!!! - else Call for a price, today!
  5. How are you writing HTML templates today? ERB (Embedded RuBy)

    Liquid (Jekyll) <html> <head><title>Ruby Toys -- <%= @name %></title></head> <body> <h1><%= @name %> (<%= @code %>)</h1> <p><%= @desc %></p> <ul> <% @features.each do |f| %> <li><b><%= f %></b></li> <% end %> </ul> <p> <% if @cost < 10 %> <b>Only <%= @cost %>!!!</b> <% else %> Call for a price, today! <% end %> </p> </body> </html> <html> <head><title>Ruby Toys -- {{ name }}</title></head> <body> <h1>{{ name }} ({{ code }})</h1> <p>{{ desc }}</p> <ul> {% for f in features %} <li><b>{{ f }}</b></li> {% endfor %} </ul> <p> {% if cost < 10 %} <b>Only {{ cost }}!!!</b> {% else %} Call for a price, today! {% endif %} </p> </body> </html>
  6. Just. look at it… Haml (HTML Abstraction Markup Language) %html

    %head %title Ruby Toys -- #{@name} %body %h1 #{@name} (#{@code}) %p= @desc %ul - @features.each do |f| %li %b= f %p - if @cost < 10 %b Only #{@cost}!!! - else Call for a price, today!
  7. Phlex is Ruby ERB (Embedded RuBy) Phlex <html> <head><title>Ruby Toys

    -- <%= @name %></title></head> <body> <h1><%= @name %> (<%= @code %>)</h1> <p><%= @desc %></p> <ul> <% @features.each do |f| %> <li><b><%= f %></b></li> <% end %> </ul> <p> <% if @cost < 10 %> <b>Only <%= @cost %>!!!</b> <% else %> Call for a price, today! <% end %> </p> </body> </html> class ExamplePage < Phlex::HTML def template html do head { title { "Ruby Toys -- #{@name}" } } body do h1 { "#{@name} (#{@code})" } p { @desc } ul do @features.each do |f| li { b { f } } end end p do if @cost < 10 b { "Only #{@cost}!!!" } else "Call for a price, today!" end end end end end end
  8. 🧐 Is this actually better? class ExamplePage < Phlex::HTML def

    template html do head { title { "Ruby Toys -- #{@name}" } } body do h1 { "#{@name} (#{@code})" } p { @desc } ul do @features.each do |f| li { b { f } } end end p do if @cost < 10 b { "Only #{@cost}!!!" } else "Call for a price, today!" end end end end end end
  9. 🧐 Also, I cheated a little bit class ExamplePage <

    Phlex::HTML def template html do head { title { "Ruby Toys -- #{@name}" } } body do h1 { "#{@name} (#{@code})" } p { @desc } ul do @features.each do |f| li { b { f } } end end p do if @cost < 10 b { "Only #{@cost}!!!" } else "Call for a price, today!" end end end end end end
  10. 👍 good old-fashioned Ruby class ExamplePage < Phlex::HTML def initialize

    def template html do head { title { "Ruby Toys -- #{@name}" } } body do h1 { "#{@name} (#{@code})" } p { @desc } ul do @features.each do |f| li { b { f } } end end p do if @cost < 10 b { "Only #{@cost}!!!" } else "Call for a price, today!" end end end end end end def initialize(name:, code:, desc:, features:, cost:) @name = name @code = code @desc = desc @features = features @cost = cost end
  11. It’s Fast • 12x faster than Rails ERB partials •

    5.5x faster than ViewComponents • 84x faster than dry-view https://github.com/KonnorRogers/view-layer-benchmarks
  12. What does that get you? Layouts Component Generator yield /

    content_for Helpers Controller Generator View Generator ApplicationView ApplicationComponent
  13. What a Controller looks like class ArticlesController < ApplicationController layout

    -> { ApplicationLayout } def index # explicit rendering is required render Articles::IndexView.new( articles: Article.all.load_async ) end def show render Articles::ShowView.new( article: Article.find(params[:id]) ) end end
  14. What’s in an ApplicationComponent? class ApplicationComponent < Phlex::HTML def h1

    = super(class: "text-3xl font-semibold my-5") def h2 = super(class: "text-2xl font-semibold mt-10 mb-5") def a(**attributes) super( class: "font-bold text-red-600 underline underline-offset-4", **attributes ) end end
  15. Custom Tags & Attributes class JiraTaskList < Phlex::HTML register_element :ac_task_list,

    tag: "ac:task-list" register_element :ac_task, tag: "ac:task" register_element :ac_task_status, tag: "ac:task-status" register_element :ac_task_body, tag: "ac:task-body" register_element :ac_placeholder, tag: "ac:placeholder" def template ac_task_list do ac_task do ac_task_status { "incomplete" } ac_task_body do ac_placeholder(**{:"ac:type" => "mention"}) do "@mention example. This placeholder will automatically search " + "for a user to mention in the page when the user begins typing." end end end end end end
  16. Reasons to NOT use Phlex • You never want to

    test views • You hate Ruby • You don’t write HTML • You don’t care about rendering performance