Skip to content

Instantly share code, notes, and snippets.

@RomanTurner
Last active July 16, 2023 16:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save RomanTurner/0ce0b8792e4149d152d2af2224cb6407 to your computer and use it in GitHub Desktop.
Save RomanTurner/0ce0b8792e4149d152d2af2224cb6407 to your computer and use it in GitHub Desktop.
A plugin for Roda for using Phlex as the rendering library of choice.
class Roda
module RodaPlugins
module Phlex
def self.configure(app, opts)
app.opts[:class_name] = app.name
app.opts[:phlex] = opts
end
module InstanceMethods
# Render a component with the default layout.
# You can change out the layout per render basis, so you are not trapped
# With the configurations. You may also send options to the layouts themselves.
def phlex_on(component, layout: opts[:phlex][:layout], layout_options: {})
title = layout_options[:title] || opts[:class_name]
layout.new(component, title: title).call
end
def phlex_layout
opts[:phlex][:layout]
end
def phlex_add_to_head(head)
current_head = opts[:phlex][:layout].current_head
if head.kind_of?(Array)
current_head.concat(head)
else
current_head << head
end
end
end
end
register_plugin :phlex, Phlex
end
end
# Example Roda App
require 'roda'
class App < Roda
# Load Custom Plugins
Dir["roda_plugins/*"].each do |route_file|
require_relative route_file
end
# Pass a reference to the default layout
plugin :phlex, layout: Shared::Layout::Homepage
# Configure Default Layout
Dir["allocs/shared/layouts"].each do |layouts|
require_relative layouts
end
route do |r|
r.root do
phlex_on(
Shared::Pages::Hello.new(Struct.new(:first_name).new('bob')),
layout_options: {title: "Phlex Test"}
)
end
r.get "hello" do
phlex_on(
Shared::Pages::Hello.new(User::DataModel.first),
layout_options: {title: "User Hello"}
)
end
r.on 'admin do
authorize_admin!
r.get 'dashboard' do
phlex_layout(Shared::Layout::AdminHome)
phlex_on(
Admin::Pages::Dashboard.new(Admin::DataModel.first),
layout_options: {title: "User Admin"}
)
end
end
end
end
## Layout Example
module Shared
module Layout
class Homepage < Phlex::HTML
attr_accessor :current_head
class Empty < Phlex::HTML
def template
""
end
end
def initialize(component, title:)
@title = title
@current_head = []
@component = component || Empty.new
end
def template
html do
head do
meta(charset: "UTF-8")
meta("http-equiv" => "UTF-8", :content => "IE=edge")
meta(
name: "viewport",
content: "width=device-width, initial-scale=1.0"
)
render vite_javascript_tag("application")
render vite_client_tag
compose_head
title { @title }
end
body { render @component }
end
end
private
def compose_head
current_head.each { |el| render el } if !current_head.empty?
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment