Summarized using AI

Building Beautiful Views in Ruby with Phlex

Joel Drapper • September 12, 2024 • Sarajevo, Bosnia and Herzegovina • Talk

In this practical talk titled Building Beautiful Views in Ruby with Phlex, Joel Drapper introduces Phlex, a Ruby gem designed to create fast and maintainable UI components for web applications using an object-oriented programming (OOP) approach. The presentation addresses common issues faced by developers, like tangled template files and weak encapsulation in traditional Ruby views, and illustrates how Phlex aims to resolve these concerns. Drapper believes that simple HTML documents generated from a backend is still the most effective way to develop web applications, especially for performance and maintainability.

Key Points Discussed:
- Common Challenges in Ruby Applications:

Developers often encounter a mix of HTML, ERB, Ruby, and Tailwind in their views, making it hard to maintain and test code.

  • Phlex's Solution:

    Phlex facilitates a component-based architecture in Ruby, promoting the creation of reusable and composable UI elements. The structure allows for testing in isolation, thereby enhancing maintainability.

  • Using OOP in Views:

    The talk emphasizes applying OOP patterns, such as inheritance and composition, to UI components which leads to better organization of code.

  • Demo of Phlex Usage:

    Drapper showcases how to create components like navigation bars and tab groups efficiently while maintaining separation of concerns and enhancing reusability.

  • Selective Rendering:

    One of the standout features of Phlex is its ability to allow the backend to render specific elements based on frontend requests, optimizing performance by reducing unnecessary rendering.

  • Component Kit Creation:

    Developers can package components into reusable kits for easy sharing and maintenance.

  • Testing and Accessibility:

    Phlex includes tools that support component testing and promotes better accessibility practices in HTML generation.

  • Challenges with Caching and Streaming:

    The talk concludes with a discussion on the trade-offs involved in caching and the importance of reconsidering streaming HTML to improve application performance.

In conclusion, Drapper's talk provides valuable insights and best practices for developers looking to adopt a component-driven approach in Ruby applications. The introduction of Phlex offers a new perspective on building UI without relying heavily on JavaScript frameworks, reaffirming the effectiveness of Ruby in modern web development.

Building Beautiful Views in Ruby with Phlex
Joel Drapper • Sarajevo, Bosnia and Herzegovina • Talk

Date: September 12, 2024
Published: January 13, 2025
Announced: unknown

In this practical talk, you'll learn how to use object-oriented programming to create fast, maintainable UI components in pure Ruby with Phlex.

Ruby applications tend to end up with a spaghetti soup of HTML, ERB, Ruby and Tailwind directives all muddled up and entangled in huge template files that become increasingly difficult to test, debug and maintain over time.

ViewComponent can help to unravel some of that, but it only goes so far. Now, many teams — including GitHub (behind ViewComponent) — are turning the view layer over to frontend JavaScript frameworks such as React.

Despite this, I still believe that returning simple HTML documents from a simple backend is the best way to build most web applications today — whether you're optimising for performance, developer productivity or long-term maintainability.

This talk introduces Phlex, a new Ruby gem that brings component-based architecture to the backend, enabling developers to create views that are fast, maintainable and really fun to work with in pure Ruby.

We'll start by identifying common pain points in traditional approaches, such as lack of encapsulation, difficult testing and poor performance.

We'll explore how Phlex addresses these issues by leveraging object-oriented programming to create reusable, composable UI components.

Through a series of real-world examples, you'll learn how to:

* Agradually refactor an existing Rails application;
* apply OOP patterns like inheritance and composition to your views;
* extract methods and objects, applying your existing Ruby refactoring skills to a new domain;
* encapsulate view logic and helpers within components;
* yield interfaces to enable composition;
* test your components in isolation; and
* package components into reusable UI kit gems.

We'll also cover the trade-offs and challenges of caching the view layer, the difference between views, layouts and components, and why you might want to reconsider the lost art of streaming HTML.

Finally, we'll learn about the emergent capabilities of a view layer that understands the structure of HTML documents, and how Phlex can help you write safer, more accessible HTML.

We'll also learn about Selective Rendering and the kinds of things that become possible when the frontend can ask the backend to render specific elements.

By the end of the talk, you'll be equipped with a set of patterns and best practices for building and maintaining component-based architectures in Ruby applications, and you'll have a solid foundation for using Phlex in your own projects, as well as a new perspective on what's possible with Ruby.

EuRuKo 2024

00:00:08.760 okay can you hear me now yeah it's like
00:00:11.240 on a
00:00:12.400 podcast uh hey everyone it's great to be
00:00:15.799 here and to see so many of my friends um
00:00:19.760 at my first ever yuu what an awesome
00:00:22.720 conference I'm Joel I'm a software
00:00:25.000 engineer from Oxford in the UK uh and
00:00:27.880 I've got about 30 minutes to cover at
00:00:29.640 least 45 minutes of content so we might
00:00:32.239 have to go at
00:00:34.760 1.5x you're okay with that right you
00:00:37.640 listen to podcast and you're not an
00:00:40.039 animal so in the run up to the
00:00:43.000 conference I got an email from the
00:00:45.320 organizers and it
00:00:47.360 said we also have a backup machine
00:00:49.600 available in case of technical issues
00:00:51.480 feel free to share your slides at least
00:00:53.399 one week before the event with
00:00:57.359 us so if we have any technical issues
00:00:59.600 today then I've got nothing for you it's
00:01:03.079 cute that they thought I'd have slides
00:01:04.560 ready this is me preparing for
00:01:08.600 yuku and this is me doing open
00:01:12.720 source I can't help it so here's the
00:01:15.439 thing about ADHD there's a spectrum that
00:01:17.799 runs from easily distracted via
00:01:19.759 functional adult to
00:01:21.920 hyperfocused so I operate here and here
00:01:26.640 and it's binary
00:01:30.320 the only way I can stay on track and get
00:01:32.280 anything done is to constantly nerd
00:01:34.119 snipe myself there are loads of tricks
00:01:36.720 and techniques uh to nerd snipe yourself
00:01:38.920 into doing things um even boring things
00:01:41.720 think about how you'd nerd snipe someone
00:01:43.159 else I wonder if it's possible to do
00:01:45.920 insert difficult thing I bet you
00:01:47.799 couldn't insert difficult
00:01:50.840 thing uh the key is the thing has to be
00:01:54.680 challenging and high quality essentially
00:01:57.880 it's about aiming higher
00:02:00.159 have you ever heard the phrase perfect
00:02:02.399 is the enemy of the good it's kind of
00:02:05.000 nonsense if you think about it because
00:02:06.719 compromise is the enemy of
00:02:09.599 motivation I think humans want to do a
00:02:11.760 really good job doing hard things really
00:02:14.840 well is much easier in some ways than
00:02:16.760 doing easy
00:02:18.800 things just want to open
00:02:28.640 this so
00:02:32.239 so people talk about 10x Engineers this
00:02:35.400 idea that some Engineers are 10 times
00:02:37.519 better than average some dismiss it as
00:02:40.760 nonsense I think 10x Engineers are real
00:02:43.879 but it's not the engineers themselves
00:02:45.640 and it's not even the problems that
00:02:46.840 they're solving so much as the way that
00:02:48.760 they're working on them 10x Engineers
00:02:51.200 are just regular Engineers who are
00:02:52.599 locked in they're nerd sniped you can't
00:02:55.680 change your boring business problems but
00:02:57.319 you can aim higher in terms of how you
00:02:58.920 solve them here's an example I think the
00:03:01.560 team at Zed the text editor are probably
00:03:04.040 some of the most productive engineers in
00:03:05.480 the world they ship and I think a large
00:03:08.640 part of the reason they do this is
00:03:10.200 because they're so ambitious they're
00:03:11.920 trying to build the best text editor in
00:03:13.560 the world and they'll move mountains to
00:03:15.000 do it for example they designed a
00:03:17.680 completely new UI framework that runs on
00:03:19.319 this GPU at 120 frames a second like a
00:03:22.840 game I think your average manager would
00:03:24.920 have said that this was Reinventing the
00:03:26.640 wheel something you're not meant to do
00:03:30.080 um something that will slow you down and
00:03:32.879 distract you from the real
00:03:34.720 task so I'm here to talk about building
00:03:37.280 beautiful views in Ruby before we get
00:03:39.879 into that I have some questions for you
00:03:42.080 um just want to kind of gauge who I'm
00:03:43.640 talking to so who loves reading and
00:03:46.040 writing
00:03:48.319 Ruby okay that's pretty much everyone
00:03:52.439 um how many of you would say it's your
00:03:54.599 favorite computer
00:03:57.360 language second favorite
00:04:00.640 top
00:04:01.879 three
00:04:04.319 okay it's top two for
00:04:07.040 me um but I won't tell you what the
00:04:09.079 other one is okay it's
00:04:12.439 CSS um people have very strong opinions
00:04:15.000 on these things I have a lot of strong
00:04:16.320 opinions too and for the next 25 minutes
00:04:18.519 I've got a microphone so strap in Jimm's
00:04:21.720 maybe
00:04:23.919 rustled why do I love
00:04:26.120 Ruby I love Ruby because it's so
00:04:28.360 flexible I find it natural to express
00:04:30.639 ideas and create abstractions in Ruby
00:04:33.440 Ruby is in its own league for this stuff
00:04:35.440 it's like nothing else what do I mean by
00:04:38.039 creating abstractions this is quite
00:04:40.360 difficult to explain it's about finding
00:04:42.120 Concepts and giving them really good
00:04:43.440 names and interfaces and then moving
00:04:45.160 them away reducing your
00:04:47.120 dependencies I like to think of these
00:04:49.320 Concepts as sort of existing whether we
00:04:52.680 codify them or not the concept of
00:04:55.520 administration ship probably exists in
00:04:57.520 your app even if you don't have an
00:04:58.919 Administration ship model and you
00:05:00.960 probably
00:05:02.639 should so it's about naming things we
00:05:05.800 start with basic logic gates we build
00:05:07.520 layer by layer on top of that First
00:05:09.080 Assembly then C then Ruby somewhere in
00:05:11.199 the middle and Ruby has objects and
00:05:12.800 variables garbage collection floats
00:05:14.479 integers arrays and strings there ranges
00:05:16.840 innumerables modules and
00:05:19.720 classes but this is just the middle of
00:05:21.720 the stack of
00:05:23.000 abstraction on top of Ruby you're using
00:05:25.080 Frameworks rails and other libraries and
00:05:27.160 finally you have your own abstractions
00:05:28.680 for your domain
00:05:30.400 you might be thinking doesn't that make
00:05:31.479 a mess with all these abstractions how
00:05:33.280 do you know what's going on it's amazing
00:05:36.160 how many times I've seen this attitude
00:05:38.639 but it's kind of like saying with all
00:05:40.319 these drawers and boxes to organize your
00:05:42.080 Lego kids how do you know where anything
00:05:43.720 is wouldn't it be easier if you just
00:05:44.800 threw it all on the
00:05:45.960 floor words that have never been spoken
00:05:48.280 by a parent in all of
00:05:50.120 history some of you were told that
00:05:53.039 duplication is better than the wrong
00:05:55.639 abstraction I think that's
00:06:02.240 there is no wrong
00:06:04.319 abstraction and doing the wrong
00:06:06.280 abstraction today if you're abstracting
00:06:08.560 well will make it easier to change later
00:06:10.319 not more difficult even if it turns out
00:06:12.479 you need to change the abstraction as
00:06:14.240 requirements change you know what's
00:06:16.599 difficult to
00:06:18.400 change lots of code is difficult to
00:06:20.960 change well okay that's true too but
00:06:23.840 what I mean is more code is more
00:06:25.919 difficult to change than less code if
00:06:28.319 you have 20 independent implementations
00:06:30.280 of the same thing that thing is not easy
00:06:32.639 to change so that's why I like Ruby it's
00:06:35.479 flexible when it comes to making
00:06:36.680 abstractions recognizing innate Concepts
00:06:38.919 and codifying them ultimately making
00:06:41.680 things more consistent and easier to
00:06:52.639 change speaking of strong opinions
00:06:56.199 what's your opinion on
00:06:58.240 Tailwind I was in two minds about this
00:07:00.639 for a
00:07:02.560 while to understand why let's look at
00:07:05.039 how I learned to write frontend code
00:07:06.479 when I first got into this stuff so
00:07:08.879 here's a pretty typical example of
00:07:10.160 what's often called semantic class names
00:07:13.319 by naming these Concepts we make them
00:07:14.800 reusable five distinct Concepts five
00:07:17.680 names kind of ties back to why I like
00:07:19.840 Ruby right did any see Adam Wan's talk
00:07:23.759 at rails world can you imagine his
00:07:26.240 reaction when he saw action View
00:07:31.280 propser Adam he did a great job of
00:07:32.720 explaining how you can use apply to
00:07:34.520 Wrangle semantic classes from tailwind
00:07:36.800 and his talk was great it always amazes
00:07:38.560 me how fast he can move in Tailwind
00:07:40.000 designing in the browser if you look at
00:07:42.199 the Tailwind website it actually
00:07:43.400 recommends multic cursor editing as a
00:07:45.240 way to handle duplication I'm not saying
00:07:47.599 this is very wrong but it's definitely
00:07:49.919 questionable if we look at another one
00:07:51.639 of Adam's projects headless UI you'll
00:07:53.560 see something like this this is view by
00:07:56.400 the way the utility classes are hidden
00:07:58.639 in the implementation of these named
00:08:01.120 components so my story with Tailwind
00:08:03.720 kind of went like
00:08:09.080 this Flex Flex is a library for
00:08:12.280 Designing objectoriented components in
00:08:15.240 Ruby it isn't a templating language
00:08:18.120 though it does have templating features
00:08:20.280 but the templating inlex is structural
00:08:22.479 it is not string
00:08:23.720 based it's also not just a DSL for
00:08:26.080 creating HTML there have been a bunch of
00:08:28.080 these over the years it all shapes and
00:08:29.479 exes and flex does draw inspiration from
00:08:31.720 many of them but Flex is also quite
00:08:33.880 different from these gems it's quite
00:08:35.800 unique so my goal today is to give you a
00:08:38.159 small taste of what's possible so you
00:08:40.279 can decide to either try it out or that
00:08:42.240 it's definitely not for
00:08:44.640 you so the heart of flex is this direct
00:08:47.560 mapping of HTML semantics to Ruby syntax
00:08:52.320 HTML has elements those are mapped to
00:08:54.600 methods it has attributes which are
00:08:56.480 mapped to keyword arguments you can also
00:08:58.320 Nest elements inside other elements and
00:09:00.320 that's all handled on the Ruby side with
00:09:02.560 blocks I love HTML but HTML syntax is
00:09:06.240 just one way to represent HTML semantics
00:09:09.320 as you'll see later there are some real
00:09:10.959 advantages to embracing this native
00:09:12.600 mapping in
00:09:13.760 Ruby however some people really don't
00:09:16.079 like it that's kind of okay here's a
00:09:19.440 some people don't like Ruby here's a
00:09:21.600 real tweet from a couple of days
00:09:25.240 ago this looks gross this Flex thing
00:09:27.680 it's so unintuitive makes me cringe I
00:09:30.160 told you Jim would be
00:09:34.760 rustled so let's look at some of the
00:09:36.680 features quickly um and then we'll get
00:09:38.720 into a demo uh Flex is designed to
00:09:41.839 structurally prevent cross-site
00:09:43.120 scripting taxs by default so if you have
00:09:45.440 a link with an href from user data Flex
00:09:48.079 knows that it's a link and will ensure
00:09:49.519 there's no JavaScript in it how many of
00:09:52.360 you really use a Content security policy
00:09:54.920 that disallows unsafe
00:09:58.079 inline since isolation Flex components
00:10:00.680 only depend on the data you pass in
00:10:02.600 making them easy to test and reuse it
00:10:05.480 also ships with test helpers for
00:10:06.800 capibara naguri noer and mini test and
00:10:11.640 aspec it has no dependencies and the
00:10:13.959 rails extension only depends on Rails
00:10:15.720 itself technically rail tie Flex can
00:10:18.800 stream responses um so bringing um time
00:10:22.320 to First Bite down in some case users
00:10:24.880 can see the first static content
00:10:26.360 rendered in their browser before the
00:10:28.279 database has even respond
00:10:29.839 responded you can render a view
00:10:31.640 targeting a specific set of Dom IDs and
00:10:34.079 flex only does the work to render just
00:10:35.639 the parts you want so this is great for
00:10:37.959 partial Hotwire updates like turbo
00:10:40.279 frames there's no time wasted rendering
00:10:42.959 the bits of the page that you don't want
00:10:44.720 and it doesn't send the bites over the
00:10:47.040 wire you can also package components up
00:10:49.440 into kits for easy reuse across projects
00:10:52.320 kits can be shared with the community as
00:10:54.279 ruby gems or kept for internal use
00:10:57.320 here's a few examples uh of third party
00:11:01.160 uh libraries of components Flex UI
00:11:03.120 protos and zest UI all built on
00:11:05.839 Flex it's also fast enough Flex renders
00:11:08.279 at about 1 gbits per second on my
00:11:11.040 MacBook Pro uh and it doesn't slow down
00:11:13.760 the more components you extract there's
00:11:15.519 no need to cach the
00:11:17.399 view Flex works great with rails
00:11:19.680 supports all rails helpers and plays
00:11:21.040 nicely with view component action view
00:11:23.000 stimulus turbo and Tailwind you can
00:11:25.279 render view components and action view
00:11:26.839 partials in flex and the other way
00:11:28.800 around
00:11:30.720 and it's just Ruby so you can use your
00:11:32.639 existing skills and Dev tools things
00:11:34.839 like Ruby LSP solar graph ruop simple C
00:11:38.600 Ruby mine they all
00:11:41.040 work so what is a component let's look
00:11:44.440 at a typical web
00:11:46.399 app
00:11:48.680 uh there are 54 icons above the fold I
00:11:52.880 think each one of these is a component
00:11:55.720 called icon I think that makes sense
00:11:58.160 they're all different in is of the same
00:11:59.920 kind of
00:12:00.959 object 14 badges there are 13 buttons
00:12:06.000 two avatars a header a file explorer a
00:12:10.079 sidebar a
00:12:13.360 menu this is the point where I have to
00:12:16.199 switch my laptop
00:12:19.279 to uh mirror my
00:12:29.320 my display
00:12:32.000 okay uh so for a live
00:12:36.079 demo me go full screen on
00:12:38.639 this um so I don't have time to show you
00:12:41.680 flex and rails but this is a quick demo
00:12:43.760 of uh some of the basic
00:12:45.880 features um so we start with a class uh
00:12:49.480 this one's just called example and here
00:12:51.680 we're rendering a heading and turns into
00:12:54.680 H1 pretty
00:12:56.399 simple uh I can I have this kit called
00:13:00.480 components which is just a module that
00:13:02.880 extends Flex kit and I can include that
00:13:06.959 module I just put an o
00:13:14.279 in and now I can use uh components so I
00:13:17.920 have a component called
00:13:23.399 nav so our nav component is wrapping
00:13:26.519 this heading uh in
00:13:30.279 Navar and we don't specify any details
00:13:33.839 about this nav from uh from this example
00:13:36.480 component that the class menu has been
00:13:39.079 added in the example in the nav
00:13:42.720 component which looks like this so
00:13:46.000 that's basic
00:13:47.440 wrapping um let's get back to the
00:13:49.680 example and I'm going to add some links
00:13:54.160 so let's say I want something like a and
00:13:57.000 we'll call this class nav
00:14:00.959 and I'm going to add a
00:14:04.000 HF and we'll just put it to slash I'll
00:14:07.600 say
00:14:13.320 home now this isn't
00:14:17.600 great the example component now um oh
00:14:23.480 I've got that in the wrong place the
00:14:25.600 example component now um knows how to
00:14:28.519 render
00:14:30.199 items uh and I don't think this is
00:14:32.480 amazing just going to save
00:14:35.079 this uh it shouldn't really know the
00:14:38.279 details of like the CSS class here or
00:14:40.839 that nav items need to be an a tag maybe
00:14:43.120 they need to be wrapped in a div or An
00:14:44.839 Li so we can take this implementation
00:14:48.440 and we can move it into the nav
00:14:50.680 component and we just Define a method
00:14:52.880 here called iton and we'll take uh the
00:14:57.519 text and we'll take the
00:15:02.199 hre we're going to replace this href
00:15:05.320 with nothing and we'll just put the
00:15:09.120 text
00:15:12.839 here so now um back in our
00:15:17.040 example uh we
00:15:19.839 can pick up the yielded
00:15:23.440 nav and we can do n. item remember we
00:15:27.240 had text followed by
00:15:29.720 the
00:15:30.880 link so now this implementation detail
00:15:35.120 and I'm I'm using semantic classes here
00:15:36.720 but you could use tell in classes is
00:15:39.720 completely encapsulated in the nav
00:15:43.240 component there's nothing leaking
00:15:45.560 outside of this and there's no
00:15:47.959 duplication and I don't know why I keep
00:15:49.800 switching to the wrong
00:15:52.920 tab so uh let's look at another example
00:16:01.440 tabs I've got a component called tab
00:16:03.920 group and it does the same
00:16:06.240 thing gives me uh T and I can do t. tab
00:16:10.720 I'm going to give it a name let's call
00:16:12.519 it tab a and I can give it some content
00:16:15.959 let's put a p in here and let's say
00:16:21.000 hello so as you can see similar kind of
00:16:24.120 thing is happening we've got tabs oh why
00:16:26.040 does it do that we got tabs we got tab
00:16:28.079 link and we got tab content and I can do
00:16:30.680 this multiple times let's change that to
00:16:35.440 B and we're doing that for multiple
00:16:38.920 tabs but what if we wanted
00:16:42.680 to have both the links rendered at the
00:16:47.360 top followed by both sets of
00:16:50.519 content the way that this is working
00:16:52.480 right now is we start rendering the the
00:16:55.600 tab group component and let me just
00:16:58.319 switch into tab
00:17:00.800 group um we hit the view template it
00:17:04.319 receives a block it creates this div
00:17:06.839 with the class of tabs and it passes the
00:17:09.039 Block
00:17:10.160 in this default implementation is
00:17:13.600 essentially the same as if we just did
00:17:16.799 yield except Flex automatically makes it
00:17:19.600 yield self unless we give it a explicit
00:17:23.439 argument so when we yield control is
00:17:26.679 given back to the caller which is
00:17:29.520 uh
00:17:30.919 here and um so this allows us to hit
00:17:34.280 this tab method multiple times while
00:17:36.600 it's
00:17:39.039 rendering and as you can see we're just
00:17:41.400 outputting this so if we wanted to
00:17:44.000 Output both sets of links followed by
00:17:46.320 both sets of content we're going to have
00:17:48.160 to do something different this will this
00:17:49.320 isn't going to work so the way that I
00:17:51.200 would solve this is I would first create
00:17:54.919 um a record for our tab so something
00:17:58.400 like tab is data. Define it has a name
00:18:02.559 it has
00:18:04.200 content uh now we want to have a list of
00:18:12.320 tabs and we want to update this uh tab
00:18:15.840 method to push into that list of tabs
00:18:18.520 when it's
00:18:19.600 called something like this thanks
00:18:22.120 co-pilot that's great
00:18:24.720 um
00:18:26.760 so now when we hit the tab component
00:18:30.000 we're actually just going to push into
00:18:31.440 this list we're going to create a new
00:18:33.440 tab each time and so this list is going
00:18:36.520 to be filled with tabs but we're
00:18:39.080 yielding at the wrong Point here right
00:18:41.320 we are yielding in the middle of this
00:18:43.280 thing so this isn't quite right we can
00:18:47.240 include Flex uh deferred
00:18:50.760 render if you can think of a better name
00:18:52.799 for this you let me know uh and then we
00:18:55.520 don't want to
00:18:57.200 yield instead we are going to iterate
00:19:00.760 over our tabs I can do tabs. each uh and
00:19:05.600 I can do yeah let's do a
00:19:08.520 button uh and let's do tabs. each
00:19:13.679 again and this time we'll do the tab
00:19:17.720 content now copilot's got this slightly
00:19:20.559 wrong
00:19:22.320 uh tab content is a block so we're
00:19:24.799 actually just going to pass it straight
00:19:27.280 in here
00:19:29.280 so now we have two buttons rendered
00:19:32.679 first and then we have two sets of tab
00:19:35.400 content and our
00:19:37.919 interface hasn't even changed we're
00:19:40.799 using exactly the same interface the
00:19:42.799 difference is the block is yielded early
00:19:44.919 and this is more strict component so if
00:19:47.480 we do something here this will not be
00:19:49.799 rendered this is like a void context
00:19:53.400 now so I have one more example if there
00:19:56.000 is
00:19:57.320 time um and that is table I'm just going
00:20:00.480 to jump over to uh my examples MD and
00:20:04.200 I'm going to copy this
00:20:13.400 one
00:20:15.559 okay so I've updated our example it now
00:20:19.760 has um this list of people which I'm
00:20:22.919 just setting in the initializer here but
00:20:24.559 obviously this would come from a
00:20:26.080 controller um and then we're going out
00:20:28.720 to this table component we hand the
00:20:31.320 table component um the people and then
00:20:34.320 it yields uh itself and then we call
00:20:38.200 column and we give it a header and a
00:20:42.200 block to calculate the body from a
00:20:45.280 single record of a
00:20:47.880 person so we can just add t. column
00:20:51.919 email and immediately our whole table is
00:20:55.559 rendered um with the names and emails
00:20:59.600 so doing this in something else would be
00:21:03.960 quite tricky you'd have to um everywhere
00:21:07.159 you use the table you'd have to iterate
00:21:09.200 over um all the headers first for all
00:21:11.919 the columns and then you would have to
00:21:13.720 iterate over all of the body text and
00:21:17.840 you'd have to try to keep those in
00:21:19.600 sync whereas given that this is just in
00:21:23.559 um in our table
00:21:25.480 component we can iterate over those
00:21:27.919 columns once here and we can iterate
00:21:30.400 over the rows and within that iterate
00:21:32.279 over the columns again this time calling
00:21:34.640 the content with our
00:21:38.039 row another thing you can do in flex and
00:21:40.240 this isn't a great example of this um
00:21:42.679 but anywhere that you
00:21:44.760 see uh something that you want to
00:21:47.320 summarize like this piece of text this
00:21:51.000 piece of code really all I want to do
00:21:53.880 when I'm looking at it from here is just
00:21:55.360 see that it is the head right so I'm
00:21:58.679 going to delete it and I'm going to say
00:22:01.799 render head or let's call it
00:22:04.840 header um and then I can just create a
00:22:07.480 private
00:22:12.120 method I'll paste it in
00:22:15.480 here and it still works it's just Ruby
00:22:19.039 so all of the normal refactoring that
00:22:20.600 you would do with Ruby works just fine
00:22:24.559 um you can imagine really big views
00:22:28.080 could just be a nice table of contents
00:22:30.400 at the top and then you can use your
00:22:31.919 symbol navigation to jump to the
00:22:33.320 relevant parts and it just becomes
00:22:35.840 really easy another thing you can do
00:22:38.400 it's a bit cheeky um though there are
00:22:41.120 there are ways you can do it that are
00:22:42.039 less cheeky is let's say I want to wrap
00:22:44.440 this
00:22:45.320 TD um I can actually just Define
00:22:48.159 TD um and I can call div and then
00:22:56.120 Super I don't know why you'd wrap a TD
00:22:58.320 but we get to put a div outside of the
00:23:00.840 super and in fact we can we can do
00:23:02.520 something inside it as well
00:23:06.720 um yeah so um what you probably want to
00:23:10.919 do actually is have a different method
00:23:12.440 that calls a TD in here and then use
00:23:14.720 that method here and that would allow
00:23:16.440 you to inherit from the table and then
00:23:18.919 layer on some extra like functionality
00:23:22.039 so you could customize how TDS are
00:23:24.640 rendered out adding a class or something
00:23:26.760 like that
00:23:29.080 uh so that is the end of the demo I'm
00:23:32.080 going to switch back to my
00:23:35.039 presentation
00:23:39.720 and I have to stop
00:23:43.480 mirroring see if we can get back into
00:23:47.000 this so building views in Ruby allows
00:23:49.799 you to create simple abstractions
00:23:52.080 avoiding duplication and
00:23:55.080 inconsistencies they fully encapsulate
00:23:57.279 specific responsibilities in the view
00:23:58.679 layer you can yield a flexible interface
00:24:01.200 with in order or out of order slots
00:24:03.919 component kits make components more
00:24:05.240 portable easier to use and share with
00:24:07.279 others plus you can install existing
00:24:09.279 kits in your own app you can use one
00:24:11.919 language instead of three Erb HTML Ruby
00:24:15.159 and compared to view components one file
00:24:17.039 instead of two heck you could put
00:24:19.080 multiple components in the same file
00:24:20.679 because they're just constants and
00:24:22.840 finally it's
00:24:26.360 fun if you try it you might like
00:24:30.360 it what's
00:24:33.200 next I'd really like to build a language
00:24:35.440 server that would allow us to offer
00:24:37.200 things like autocomplete for HTML
00:24:38.640 elements and attributes go to definition
00:24:40.679 for components and optional Tailwind
00:24:42.919 autocomplete even when using conditional
00:24:45.080 CSS classes additionally Source Maps
00:24:48.240 would allow us to build Dev tools that
00:24:49.679 allow you to inspect components in the
00:24:52.200 browser and just like jump straight to
00:24:54.240 definition in your code editor by
00:24:55.559 clicking on a component in your browser
00:24:58.520 Flex JS and mor Flex similar to Turbo
00:25:01.080 Flex JS um which we're working on will
00:25:03.720 take advantage of flex unique capability
00:25:05.880 of selectively rendering on the server
00:25:09.039 morflex is a Dom morphing Library uh
00:25:11.279 that we wrote to support FX JS um its
00:25:14.960 algorithm is top to bottom like Flex JS
00:25:17.279 sorry like Flex which means we should be
00:25:19.039 able to support streaming
00:25:21.640 doring form uh forms are the trickiest
00:25:25.360 components to build in rails in my
00:25:26.960 experience I would really like to share
00:25:29.240 some generic abstractions uh to help
00:25:31.760 with this uh so that's something I'll be
00:25:34.279 working on soon and finally first party
00:25:37.600 component kit uh we've got Flex UI
00:25:40.360 protos and zest UI uh I have finally
00:25:44.039 decided that I'm actually going to build
00:25:45.520 a first party component kit I'm not sure
00:25:47.679 what it's going to be called um but the
00:25:52.399 uh the um who was it the the laravel
00:25:57.360 people who made a component kit called
00:26:00.120 flux um spell with an F so maybe maybe
00:26:03.279 that will be some
00:26:05.080 inspiration uh if you want to find out
00:26:07.080 more information there's a link here um
00:26:09.679 to the beta website um Flex 2 is
00:26:13.480 releasing probably today uh as a beta
00:26:17.360 and um there's also a link from there at
00:26:20.200 the top right hand corner to the naming
00:26:22.440 things Discord
00:26:24.440 Channel thank you
Explore all talks recorded at EuRuKo 2024
+39