Phlex already works with Sinatra (and everything else) but its normal usage leaves you without access to Sinatra's standard helper methods. This extension lets you use Sinatra's url() helper method from within a Phlex view (along with the rest of the helper methods available in a Sinatra action).
Add phlex-sinatra to your application's Gemfile and run bundle install.
gem 'phlex-sinatra'Then require it in your app:
require 'phlex-sinatra'Use the phlex helper method to render a Phlex view and pass an instance of the Phlex view (instead of using .call to get its output). For a classic-style Sinatra app it'll Just Workβ’:
get '/foo' do
phlex MyView.new
endFor a modular app the extension must be explicitly registered:
class MyApp < Sinatra::Base
helpers Phlex::Sinatra
get '/foo' do
phlex MyView.new
end
endYou can now use Sinatra's url() helper method directly and its other methods (params, request, etc) via the helpers proxy:
class MyView < Phlex::HTML
def view_template
h1 { 'Phlex / Sinatra integration' }
p {
a(href: url('/foo', false)) { 'link to foo' }
}
pre { helpers.params.inspect }
end
endYou can also pass an alternative content type β which defaults to :html (or :svg for a Phlex::SVG instance):
get '/foo' do
phlex MyView.new, content_type: :xml
endIf your entire view layer uses Phlex then layout will be a part of your component structure but maybe you've got an existing non-Phlex layout or you don't want to use Phlex for everything, in which case standard Sinatra layouts are supported.
Pass layout: true to wrap the Phlex output with Sinatra's default layout -- a file named "layout.erb" in the configured views directory (ERB is the default) -- or pass a symbol to specify the file:
get '/foo' do
# This Phlex view will be wrapped by `views/my_layout.erb`.
phlex MyView.new, layout: :my_layout
endOther Sinatra templating languages can be specified via the layout_engine keyword:
get '/foo' do
# This Phlex view will be wrapped by `views/layout.haml`.
phlex MyView.new, layout: true, layout_engine: :haml
endIt's also possible to call phlex from within other views, for instance an ERB template:
<%= phlex MyView.new %>A layout can also be passed:
<%= phlex MyView.new, layout: :wrapper %>Streaming a Phlex view can be enabled by passing stream: true which will cause Phlex to automatically write to the response after the closing </head> and buffer the remaining content:
get '/foo' do
phlex MyView.new, stream: true
endEven with no further intervention this small change means that the browser will receive the complete <head> as quickly as possible and can start fetching and processing its external resources while waiting for the rest of the page to download.
You can also manually flush the contents of the buffer at any point using Phlex's #flush method:
class Layout < Phlex::HTML
def view_template(&block)
doctype
html {
head {
# All the usual stuff: links to external stylesheets and JavaScript etc.
}
# Phlex will automatically flush to the response at this point which will
# benefit all pages that opt in to streaming.
body {
# Standard site header and navigation.
render Header.new
yield_content(&block)
}
}
end
end
class MyView < Phlex::HTML
def view_template
render Layout.new {
# Knowing that this page can take a while to generate we can choose to
# flush here so the browser can render the site header while downloading
# the rest of the page - which should help minimise the First Contentful
# Paint metric.
flush
# The rest of the big long page...
}
end
endIt might not seem obvious at first why you'd use url() at all given that you mostly just pass the string you want to output and then probably false so the scheme/host isn't included.
There are a couple of reasons:
-
Linking to a full URL
Sometimes you need to link to a page on the site using its full URL β for instance within a feed or for an
og:imagesocial media preview image link. -
Awareness that the app is being served from a subdirectory
This isn't something you encounter very often in a standard Sinatra app but you hit it quite quickly if you're using Parklife to generate a static build hosted on GitHub Pages β which is exactly what prompted me to write this integration.
In this case by using the
url()helper you wonβt have to change anything when switching between serving the app from/in development and hosting it at/my-repository/in production β internal links to other pages/stylesheets/etc will always be correct regardless.
Bug reports and pull requests are welcome on GitHub at https://github.com/benpickles/phlex-sinatra. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the phlex-sinatra project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.