Sure ERB is another DSL and some things are not perfect. But for the mark-up you write actual HTML instead of having to learn and get used to writing blocks for each element.
I guess to each their own, you enjoy rails with Phlex and I will with ERB.
I think the bigger challenges with emails is that action mailer itself is a little dated and feels cluttered. Most email clients being a nightmare with the actual rendering and not being able to use stylesheets etc makes it even harder... So I'd love to see a general iteration on action mailer to bring it up to the level of Rails 8
Agreed.
This has been tried so many times, and non of them really "stuck". HAML, slim, liquid and now phlex. All "DSLs" to some extent that solve the problem of "not having to write HTML".
Is that a problem, really? People writing Rails apps are developing web-apps. Writing HTML is part of the skillset, and of all the things in a Rails app, really not the most difficult, boring or inefficient ones.
I've found the opposite to be true: another layer of abstraction that new hires need to understand. Another DSL to learn. Another syntax/LSP/docs to add to the IDE, or editor. Another leaky abstraction that has to be debugged, monitored, performance-tested. And a very strongly and tightly coupled dependency: it's almost undoable to just move from, say, HAML back to erb in a 10k+LoC rails app: you're effectively married to HAML, and truly in trouble when (not if) the gem gets abandoned.
Now, like Cells[1], Phlex main "problem it solves" isn't "HTML is hard" but "Rails' templates are too simple/poorly designed". Rails templates push a lot of magic (global) state around, is bidirectional (you can update the database from within a template just fine. Both intentional and accidental), it's not isolated, and because of all this, very hard to test. All this becomes worse if you want to re-use components.
But, like Cells, Phlex solves this problem by introducing some DSL to abstract the HTML. Which then makes up the largest part of the gem. Why? Really. OOP templates can be classes that have a "render" and that then use (scoped) "erb" files just fine. This pattern is both easy and available - no gems needed even.
So, yes. My opinionated, advice, fed by decades of struggling with numerous rails projects, is to stay away from such gems: KISS.
The thing about Phlex is it’s actually one less thing to learn. Instead of learning Ruby and ERB and how to use them both with HTML — and all the context switching that goes with using three languages in one file, you only need to know Ruby and HTML semantics (elements, methods, attributes, text, comments, doctype).
> Another syntax/LSP/docs to add to the IDE, or editor.
If you’re writing an app in Ruby, you’ll already have Ruby LSP set up in your editor. There is no other syntax. I would strongly advise against using Phlex if not already writing an application in Ruby, though I have heard of someone using Phlex to generate PHP.
> Another leaky abstraction that has to be debugged, monitored, performance-tested.
I don’t know what you mean by “leaky abstraction”. I consider Phlex to be an air-tight abstraction around the parts of HTML I’ve ever had to use in the last 15 years of programming. There are a couple of things you can’t do without using `raw` — mainly CDATA and other non-HTML5 doctypes.
If I saw a convincing argument for supporting those parts of HTML, I would.
The real leaky abstraction for HTML is string templating, where none of the HTML semantics are validated and XSS vulnerabilities abound.
With actual XML and JSON (or csv etc) I would agree: for that you need a serializer, not a string templating env.
But for HTML, especially when used to build GUIs, string templating makes sense - to me -.
What I meant with "leaky abstraction" is that when I write a web-app, my goal is to write certain HTML, the actual strings, to a browser. I'll have my developers console open, inspect DOM/source and then modify the code of the app until the DOM/source matches what I want or need it to be. The closer my "code of the app" is to this actual DOM/source, the less I need to think through layers.
I prefer to just "move this UL out of the DIV and next to the H2¹" rather than manipulating the structure in a tree of objects. To each their own, I guess, but I rather prefer to stay "as close to the metal" as possible, especially if that metal isn't complex or difficult.
¹ I realized I wrote my HTML elements in capitals. I am that old; and I don't anymore, but old habits creap in, I guess :)
If you know those things then you basically know ERB. And to your point the Ruby LSP works with ERB.
I agree on your criticisms of Erb and ActionView. I'd add that Erb is just really noisy jumping in and out of Ruby with <%= %> constantly. I'm regularly running down basic errors in producing well-formed HTML.
I'm still only experimenting a little with Phlex. I'm not sold on some of its design like the distinction between views and components, but maybe that's a practice/docs issue. I'd also like to see a performance test that's not a microbenchmark and I may try to make one this month. Similar to your note about haml, I've told the project devs that I'd be really encouraged by a phlex -> erb tool to reduce the perceived risk of getting locked into the dep.
EDIT: Oh, and I read the phlex code because I have similar experience outliving a dep. The library is ~1,600 loc with same again in tests. There's a little metaprogramming in SGML::Elements I dislike but it's not a dealbreaker. The library is small and straightforward enough that I'd be surprised if it broke without going unmaintained 5+ years, and I'd be fine maintaining a private fork for a year or so while migrating off.
There is no distinction in Phlex. The distinction is only made in generated code in Phlex-Rails where it felt like a sensible way to fit with the existing mental model. Views are technically just components, but they are expected to be HTML documents composed of components and rendered directly from controller actions. You wouldn’t want to render a view inside another component because you’d get another doctype and `<html>` tag. So they are sort of “entry points”.
> There's a little metaprogramming in SGML::Elements I dislike
Many crimes are committed in the name of performance. For example, we have a different code path for standard elements with attributes and content, standard elements with attributes but no content, standard elements with content but no attributes and standard elements with no attributes or content. Not to mention void elements.
This allows us to reduce the number of string concatenation operations required during rendering and is why it renders ~1.5gbps of HTML per core.
I’ve considered having an API-compatible minimal version of Phlex that would be much easier to take on and maintain yourself if it didn’t make all these performance optimisations.
It would be great if you could expand your explanation of the metaprogramming into a comment in the code. When I read it, I didn't immediately recognize the technique and its tradeoffs, so it seemed like an odd decision rather than an informed one.
Having two versions of phlex would be a strong negative to me. I don't like to see dev teams spread themselves out, it's one more choice I'd have to make when adopting, if switching between them I have new risks that they've slipped out of sync in some way, and it's altogether another odd decision that has to be explained.
What I was trying to say about the code is that I share the previous commenter's experience of "welp I guess if we want that bug fixed we have to click 'fork' on github... while we write up our plan to migrate away". Having had that experience several times, Phlex looks like an acceptable risk.
I don't think of Phlex as something that lets me get away from writing HTML. I see it as a tool that allows me to bring all my experience and skills of writing clean and well organized Ruby code to the view layer. Am I repeating this same bit of markup frequently? Let's extract that out into a method. Are these two pages basically the same, only differing in one section? Perhaps they should share a common base class.
When I first started using Phlex, this wasn't even on my radar. My thought was that it was just a HTML builder DSL in Ruby, so what? The "so what" didn't hit me until working with it for a while. All my views are now Ruby—not text files with bits of interpolated Ruby. And in the 15 years I've been writing Ruby, I've picked up some skills at keeping it maintainable and readable. Skills that I can now apply to the view layer in a way I never could before.
So all of that is to say: I think I understand the reservations you lay out, and I had some of them as well. But I think there is more under the surface if you ever have the opportunity to give it a chance.
And just real quick, regarding this:
> you're [...] truly in trouble when (not if) the gem gets abandoned.
Phlex is sometimes described, somewhat tongue-in-cheek, as a string concatenation toolkit. At its core, it just builds strings. It is unlikely to stop working unless Ruby has some major changes. It is possible that the phlex-rails integration could go stale after a few Rails releases, if it was not being maintained. As long as Rails can send a string response, Phlex will remain usable.
Slim made views way easier to look at, understand, and code. I personally gained a lot of efficiency working with it.
I just got done porting https://www.skatevideosite.com (and our custom admin panel) from sveltekit/fastapi to Rails and I'm stoked on the results so far.
I need to write up my experience about the rewrite, having a blast so far.
- People inventing new technologies to not write SQL
- People inventing ways to avoid writing HTML
I feel like the solution to both of these is just to stick to SQL / HTML as for both of these there's a lot of resources, tooling and knowledge and they will not go away. They are transferable between languages, projects and whatever tooling companies are using.I like SQL alright from a functionality perspective (the syntax leaves much to be desired), but I still use ORMs where appropriate just to be able to modularize and make reusable behavior where it makes sense.
- People inventing new technologies to not write JS
- People inventing new technologies to avoid writing CSS