The purpose of this post is to collect feedback on new Rails feature proposals, and I’ve put together a Pull Request. I welcome any comments, either here or on X or BlueSky
Translation: Ph.D.
I’d like to propose an extension to Ruby on Rails TagHelpers that will allow us to create HTML structures that were previously cumbersome.
In short, the view helper code would be written like this:
The proposed approach allows us to write more complex HTML using only tag helpers (without ERb), using code that closely reflects the structure of HTML. This will simplify the creation of UI components.
While I completely agree that Phlex is awesome and refreshing, I hope my proposal addresses at least one of Adam’s main complaints and allows us to actively re-evaluate traditional Rails ERb and view helpers.
In short, I don’t want to throw out the baby with the bathwater.
Let’s take a look at ViewComponents and Phlex first
Before delving into the details of my proposal, let’s take a look at how to write the above HTML using ViewComponents and Phlex.
I hope this illustrates my point, which can be summarized as “Why do we need to write a new category for 4 lines of HTML?”.
Both ViewComponent and Phlex are class-based, making them ideal for components that need to encapsulate logic.
However, with the rise of Tailwind CSS, we were encouraged to write many smaller components whose sole purpose was to dry out our code and save us from writing tons of CSS classes – which had little to no internal logic. In these cases, ViewComponents and Phlex may be overkill.
In many cases, the traditional view helpers included with Rails are sufficient for this purpose. For example, for the following HTML, you can write a very easy-to-understand helper that mirrors the HTML structure as shown below.
With two children, you can write a view helper that’s hard to read, or more commonly, you can use ERb.
Although I fully understand that ERb is better than the view helper at rendering highly complex HTML, I find it difficult to accept the idea that simply increasing the number of children from 1 to 2 will make the HTML more complex. I’m uncomfortable with the idea that this alone forces us to use ERb instead of view helpers.
Given this situation, I came up with the idea of making it easier to write HTML elements with multiple child elements in a view helper by adding a markup helper feature.
Why doesn’t tag helper work when there are multiple children?
If we write the following code in the view helper, we will lose tags and get only .
This is because the value returned do Blocks used as content
Label. since tag.figcaption is the last expression in the block, and that value becomes the content. this tag.img Lost because its value is not captured anywhere.
I recommend using the following syntax. We extend the tag helper to optionally provide variables (in this case b for “buffer”) to block. we promote tag.img and tag.figcaption to this buffer (b), which is implemented as an array. After the tag helper generates the chunk, it executes safe_join Produces HTML containing two child elements on the buffer and will be used as
Label. This behavior is only triggered when the number of blocks is 1 or greater, ensuring backwards compatibility. (The current implementation of tag helper does not use block variables)
The resulting code is tightly integrated with the structure of HTML and is easy to compare. Even someone with little knowledge of Ruby should be able to understand what’s going on.
benefit
With this proposed feature, developers who are hesitant about using ViewComponents or Phlex can better benefit from components while sticking with traditional ERb and view helpers.
It also provides a mechanism for creating widgets using functions (view helpers) that is easy to understand for non-Ruby developers (that is, designers). Note that React elements are also functions, not classes.
This feature allows us to implement slightly more complex elements in the View Assistant without having to resort to ERb templates. Compared with ERb, the advantages are the ability to accommodate multiple components in one file, explicit interface, simpler API calls (no need to write render "[path to partial]", [hash of locals] This can get verbose) and performance.
What about unit testing?
One of the common benefits of using ViewComponents or Phlex instead of ERb and view helpers is the ability to unit test components.
Although I’ve been using variations of this technique for years, I recommend adding it to Rails to make it more convenient and raise awareness of the technique. safe_join technology.
I’m currently preparing the implementation and pull request. In the meantime, if you have any comments or comments, I’d love to hear them!