2.1.1
[Experimental] support for ERB snippets
In this non-breaking release, we’ve added support for ERB snippets. Anything that you would have defined as a Ruby method, e.g. view_template
can now be defined as ERB.
Basic inline example
In this example, we create a Nav
component and define its view_template
using ERB instead of Ruby. The erb
class method defines the view_template
method with the compiled ERB for us. We also expose an item
snippet — again defined with ERB. This time it defines the item
instance method. Here, we specify locals: %(href:)
, which means the method will be defined as def item(href:)
.
class Nav < Phlex::HTML
erb :view_template, <<~ERB
<nav>
<% yield %>
</nav>
ERB
erb :item, <<~ERB, locals: %(href:)
<a href="<%= href %>">
<% yield %>
</a>
ERB
end
Locals
You can put anything in the locals
string that you would regularly put in a Ruby method signature:
Required positional argument
erb :method_name, <<~ERB, locals: %(foo)
Optional positional argument
erb :method_name, <<~ERB, locals: %(foo = nil)
Positional argument with default
erb :method_name, <<~ERB, locals: %(foo = "test")
Required keyword argument
erb :method_name, <<~ERB, locals: %(foo:)
Optional keyword argument
erb :method_name, <<~ERB, locals: %(foo: nil)
Keyword argument with default
erb :method_name, <<~ERB, locals: %(foo: "test")
Note: we may rename locals:
to params:
or something else. Send us your feedback.
Sidecar templates
Instead of defining the ERB templates inline, you can alternatively define them as sidecar files. You’ll still need to define the method signatures in your component. Let’s go back to our nav component. We can remove the inline ERB.
class Nav < Phlex::HTML
erb :view_template
erb :item, locals: %(href:)
end
If this Nav
component is defined in app/components/nav.rb
, Phlex will search for the following sidecar files:
app/components/nav/view_template.html.erb
app/components/nav/item.html.erb
In the case of the view_template
snippet, If Phlex can’t find app/components/nav/view_template.html.erb
, it will also try app/components/nav.html.erb
.
Performance
All ERB templates are compiled into methods once at boot so performance should be excellent.
Compatibility
For the most part, these ERB snippets should be completely compatible with Ruby snippets and all the Phlex features like fragments, caching, etc. When it comes to caching, the technique we use to bust the cache when you make changes in development mode with Rails will not work if you use external sidecar ERB files.
Security
Because ERB is not structural, we can’t provide all the same security features. It is possible, for example to write ERB like this, and since we don’t know you’re writing to an href
attribute, we can’t strip javascript:
from the start of the href
.
<a href="<%= user_data %>">Click me</a>
The main concern with inline ERB support was making sure you couldn’t unintentionally interpolate unescaped user data with #{}
interpolation. Our solution to this is to only support the definition of ERB snippets at the class level where it’s very unlikely any user data will be in scope.
The correct way to output user data is with <%= %>
tags, though it can’t be as safe as regular Phlex output because it is string-based, not structural.
PRs
- [EXPERIMENTAL] Add support for ERB snippets and sidecar templates by @joeldrapper in #867
Full Changelog: 2.1.0...2.1.1