Replies: 1 comment 9 replies
-
This is awesome! I need to take some time to go through your examples in more detail, I just wanted to quickly point out that You could use use |
Beta Was this translation helpful? Give feedback.
9 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Sorry in advance for a long post... The last few days, I've been refactoring the public-facing part of a hobby project to use Phlex, and I love it! Since the documentation has few real-world examples - understandable, for such a new gem! - I thought I'd share parts of my structure here. Maybe I've had a good idea you didn't consider, or maybe you can tell me how I can improve my code - sharing is good anyway!
I have a
StudyProgramme
model thathas_many :photos, through: :photo_combinations
.Photo
is the other way, andPhotoCombination
belongs_to both. Standard stuff. I do it like this because I have a caption field on the PhotoCombination since captions depend on context and thus can’t be set on the photo model itself. I often have four or five photos per StudyProgramme, the top photo I use as featured image, and the rest goes in a slide show below the text. My backend view is still an erb_form
with nested forms with a Cocoon-based Photo chooser with a caption on the PhotoCombination model. Messy (and irrelevant, since we're talking about Phlex), so I won’t bore you with it.After I refactored the view and deleted
study_programmes/show.html.erb
, I have this in my controller:This is my study programme view (I put it under a "templates" namespace, but it could easily be called page or whatever):
As you can see it renders three more views, in addition to a layout. This is my layout.
The last two methods are only because I’m using vite_rails for assets, but if you use Webpacker, the logic would be similar. (Vite outputs the stylesheet tag automatically if you import it in the javascript entrypoint, that’s why there’s no styles here.)
Next, we’re rendering the top image:
This has a few pieces of Dragonfly-specific logic, so feel free to disregard that. Basically, the complexity is because I wanted to have one featured image component for several use cases. This component resizes and crops (with center gravity) if you pass width + height to render, but only resizes if you pass only width. I use lazy: false on the top image here, because it’s a good practice to not use
loading="lazy"
on above-the-fold images. Both caption, lazyloading and cropping are optional based on the render arguments. Markup: I use two webp sizes in a picture element, with an img/jpg fallback, as suggested by Andrea Verlicchi here. The inline style is for setting aspect ratio CSS dynamically. I think this is a smart solution to the cumulative layout shift problem - no more padding-bottom hack!Next, I have a super simple body text component that’s for rendering an HTML text field from the database. Heading is optional and is provided by the ProgammePage and passed to the Body view. (The way I do it here, the heading might as well be in the ProgrammePage template/component, but if we're going to, say, wrap the heading in classes, it would get ugly fast, and it would then make sense to make it parts of this component or even a separate heading component.)
I use the Rails sanitize helper for the text itself. If we were going to write plenty of these, we could abstract the raw helpers.sanitize bit into application_view or something, but in this app I want to use this Body component for every HTML-from-database part of the application, so it would likely only be used once, i.e. here.
The next part is using the as of now undocumented collection feature. It’s probably not a good idea to use this before the syntax is stable, but I’m just playing around and wanted to try it (I will update this example when/if the feature changes). (UPDATE 30 Jan 2023: the experimental collections syntax was removed in Phlex 1.3.0., so this code will not work. I might rework this example with the new syntax at some point.)
Rendering the lightbox, I’m reusing the top image component for the item_template!I found this really cool, and since my TopImage component is so flexible, these items will - unlike the top image above - only be resized (not cropped) and they will be lazy loaded.
This gives the following structure:
...where components are meant to be shared across the application, and templates are meant to be collections of render calls (more or less) to components, and the layout (more than one is also a possibility!) the birds-eye view.
That’s it so far! Hopefully this will help someone. If I’m doing things in a weird way, please let me know!
I’ve loved doing this so much. I actually really like HTML syntax (I need help, obviously!), so I’ve never warmed to haml or slim and stayed with erb. For this reason, I thought writing HTML with the Phlex ruby dsl would feel wrong. However, recently, I’ve had to use much more erb tags and the constant back and forth between straight html and erb blocks like
<%= options_for_select(etc, etc) %>
makes my head hurt, even with judicious use of helper methods (which I don’t like either, because of context switching). Phlex is the first time I really enjoyed writing view code. (Also, it's crazy fast!) Looking forward to rewriting more of this project with it.Beta Was this translation helpful? Give feedback.
All reactions