00:00:02.610
Are you ready for the next talk? I want to introduce our next speaker.
00:00:09.510
His topic is Mate Stack UI, and I want to give a huge shout-out to him.
00:00:16.500
Thank you! Ok, hi everyone.
00:00:24.439
I want to introduce you to Mate Stack UI. If you don't know what Mate Stack is, I'm going to change that during this talk.
00:00:31.649
The goal is to rapidly create a dynamic web UI in pure Ruby. I pitched it this morning, and I'm going to give a longer version of the pitch right now.
00:00:37.829
First of all, I'm Jonas. I studied mechanical engineering and taught myself software engineering during my studies.
00:00:43.230
I fell in love with software engineering, but if I take a moment, you might wonder why that is.
00:00:51.329
I didn't study computer science, so I have a very high-level view on software engineering.
00:00:56.820
You might have noticed that I'm a co-founder of Base Mate, a software service agency.
00:01:03.120
I'm the creative mastermind, and that's why I wanted to introduce Mate Stack today.
00:01:10.800
Now, I have some questions. Please raise your hands: Who of you loves to write HTML?
00:01:18.030
Ok, who loves to write CSS?
00:01:27.030
And who loves to create a JavaScript mess for some dynamic behavior?
00:01:39.150
Oh yeah, that's quite a few hands! And who has to implement Ruby business logic?
00:01:48.810
Exactly, it's a tough situation.
00:01:54.360
I didn't expect so many hands for HTML and CSS! So, why this talk?
00:02:05.190
I should have looked there; by the way, this is my first talk in front of an audience with this type of microphone.
00:02:11.640
Let's have a look at how a Rails developer faces the challenge of creating a dynamic user interface.
00:02:17.560
We'll examine how much Ruby can be used while facing this challenge.
00:02:29.980
We model the database, use Active Record, and it's beautiful.
00:02:35.530
We love it! The definition and the API are fantastic; many people adore them.
00:02:43.230
We use controllers, such as the application controller, and everything just works.
00:02:49.270
The code looks nice and is highly maintainable.
00:02:54.840
In my opinion, it's also very beautiful.
00:03:02.080
We use gems like Devise to set up authentication; we all know that.
00:03:08.080
You can connect it to your controller, and the architecture is clean and maintainable.
00:03:16.830
It is stunning.
00:03:23.050
Then, personally, I use Pundit for authorization. There are multiple gems for that.
00:03:32.050
We can handle more than just authentication; we also manage authorization beautifully.
00:03:37.680
And we define routes according to what Rails has to offer, which is also beautiful.
00:03:46.750
You can accomplish a lot and perform many magic tasks, saving time and delivering applications quickly.
00:03:55.470
Everything looked good until now, but then the view layer comes into play.
00:04:01.750
That's at least my reaction when I start implementing the view layer.
00:04:12.580
So, you essentially have two options: you can write .erb or humble views.
00:04:18.940
You can manage to avoid writing proper Ruby while adding some JavaScript for dynamic behavior.
00:04:30.400
However, this method often leads to a poorly structured view layer.
00:04:38.520
At least it's part of your Rails application.
00:04:44.139
Alternatively, you can use a modern approach and create a standalone JavaScript application.
00:04:52.060
You can leverage one of the major JavaScript frameworks.
00:04:57.550
In this scenario, Rails is often used just as a JSON API.
00:05:05.349
You handle all the rendering in your standalone JavaScript application.
00:05:12.039
This leads to having a well-structured view layer since they offer good software design.
00:05:20.770
You don't want to say anything negative about that.
00:05:26.800
This approach is well-structured, but it means you have to write a lot of JavaScript.
00:05:33.009
This is where the problem begins because I don't enjoy that.
00:05:38.469
The most important consideration is maintaining two different applications: your Rails back-end and your JavaScript front-end.
00:05:46.029
You have to align these systems and create APIs, which often leads to losing functionality.
00:05:52.569
You may find yourself managing authentication and authorization across both systems.
00:06:00.990
You even have translations living in the back-end, and you need to duplicate them somehow on the front-end.
00:06:07.990
In my opinion, there are many disadvantages to having two different applications, two repositories, and two test suites.
00:06:13.860
We don't like either approach, obviously. If I say 'we,' I mean me, my colleagues, and some people I know.
00:06:21.389
The first approach, the HTML/ERB or Slim option, feels too limited.
00:06:28.650
The second approach, creating a standalone JavaScript application, is deemed too complex.
00:06:35.710
This gap in between is why we created Mate Stack.
00:06:46.670
I would like to show you real working code to give you an idea of how we want to fill that gap.
00:06:53.980
Now, I'm switching to my editor. From now on, I encourage you to ask questions right away.
00:07:03.419
If I'm going too fast, it's because everything looks perfectly natural to me. So let me know if you don't understand anything.
00:07:10.210
Ok, nice. We have a not styled app here.
00:07:16.560
On purpose, I haven't added any styles because we're focusing on functionality right now, not about Bootstrap or Material Design.
00:07:22.020
So, let's have a look at what Mate Stack looks like. I'm going to switch to the editor.
00:07:30.889
Is that ok for everyone? I can make it a bit bigger.
00:07:39.300
Better? Still a bit too small? Ok, I think it's fine.
00:07:44.520
Alright, cool. So, we can see part of the page here.
00:07:50.789
Actually, don’t care too much about what this is on top. As you can see, it's a Ruby class.
00:07:57.210
We should have a look at the response part. Mate Stack has the concepts of a page, a component, and an app.
00:08:03.539
These are the three major building blocks, and we will see what each one entails.
00:08:08.789
At the moment, we're looking at the page class, which has a response function.
00:08:13.889
In this response function, the page orchestrates components.
00:08:20.669
In this case, we describe how the user interface should look.
00:08:26.550
If we switch back, we see this output: 'Hello from page one.' This is, obviously, the first output we orchestrated.
00:08:32.849
This is a heading component, similar to an h2 HTML tag. This is our component call.
00:08:39.240
We have a div; we know what that is, and if we wrap plain text output... hello from page one.
00:08:46.380
The first thing we see here is that we are not writing HTML; we're writing Ruby in a Ruby class.
00:08:53.160
You can imagine we could put a lot of Ruby on top of it. Now we're going to do just that.
00:09:01.660
But that's just the first major component.
00:09:05.910
We describe the user interface in Ruby.
00:09:12.660
The next thing to examine is that there's more on this page.
00:09:18.810
There's obviously some kind of layout, like a title and a navigation bar.
00:09:24.370
So a page may have a layout, and we called it the Mate Stack app.
00:09:31.759
The Mate Stack app can contain multiple pages, but at its core, an app is just a layout for a page.
00:09:38.410
The term 'app' sounds fancier.
00:09:44.710
Again, we have different classes at play here, and now we have the app class.
00:09:50.080
We're applying the same principle that we have a response function orchestrating components.
00:09:57.370
We can have an h1 tag with the text 'My App,' followed by a navigation part with transition components.
00:10:04.210
These are special Mate Stack components you'll see what they do. You might expect what they will do.
00:10:10.950
Again, we declare our user interface with some buttons.
00:10:18.980
Here we have six buttons, each leading to different routes.
00:10:25.680
We also have a main part, a content area for the page, which behaves like a Rails layout.
00:10:32.700
It has a yield like Rails layouts do.
00:10:39.400
What you just saw is the first page with this content filled into the layout.
00:10:46.100
Again, that's just the basics. Mate Stack serves static content, but magic happens now.
00:10:53.500
If I click this button, it may not be easy to see, but there is no page reload.
00:11:00.470
It internally switches out these two pages.
00:11:09.750
We'll quickly have a look at page two.
00:11:15.370
Page two, as we introduced here, uses a prepare statement. This should be done before rendering.
00:11:21.100
So we initialize an array of strings and orchestrate some sub-components.
00:11:28.929
As you can see, they are just HTML tags familiar to you, but implemented in Ruby.
00:11:35.570
We have a list, and we iterate through this array to display the content.
00:11:42.460
The main thing is that the transition between these two pages is done through Mate Stack magic.
00:11:49.640
No JavaScript is involved on our part.
00:11:56.100
This is critical for us as it's a classic requirement for a dynamic user interface.
00:12:02.370
You want to handle page transitions with animations and loading bars. Normally, this would require writing JavaScript.
00:12:10.860
But because it's a classic requirement, we don't want to write JavaScript.
00:12:18.430
We want to define the behavior in a Ruby class where it can just happen automatically.
00:12:25.900
This is one of the main concepts of Mate Stack: dynamic page transitions.
00:12:32.570
I can show you how that looks if you take a look at the network.
00:12:39.450
Just to wait, I will switch to page one.
00:12:47.670
As I switch, I just get the content back from the server for page one.
00:12:54.800
Mate Stack's JavaScript, which is based on Vue.js, takes this content and displays it in the area.
00:13:02.209
If you can imagine, that's the same structure.
00:13:09.639
Ok, questions up to this point?
00:13:16.339
Until now, we have seen two major things: HTML written in a Ruby class and dynamic page transitions.
00:13:23.060
These are based on some magic, and Mate Stack ships them automatically.
00:13:30.519
Any questions? Is everything clear?
00:13:35.950
Cool. There was a question, right?
00:13:42.090
Just a quick question: is this compatible with other Ruby-based frameworks like Sinatra, or is it mostly a Rails gem?
00:13:48.420
Currently, it's built for Rails, but I know that this can be a requirement, and we are looking to port it to other Ruby frameworks.
00:13:56.540
At the moment, I started with Rails because we do client projects there and validate our ideas in our daily business.
00:14:03.880
So I didn't want to build something that doesn't work in reality.
00:14:08.070
That's why we built a Rails engine; you just plug it into your Rails application.
00:14:15.640
Then you get these functionalities out-of-the-box. We use that in our production client systems.
00:14:21.990
Ok, Mate Stack has a lot more to offer. We will see a bit of that right now.
00:14:29.300
Now we're going to dynamically transition to page three without a page reload!
00:14:35.950
And here it is, page three! Let's see what happens next.
00:14:43.390
There’s a button and a date string, so if I click it, you'll see a new string.
00:14:50.380
And some kind of notification will appear. Let's see how this is implemented on my third page.
00:14:58.360
Once again, we orchestrate components in this page. We have our action component.
00:15:07.530
This component gets a configuration, which is defined in a Ruby function.
00:15:14.130
This Ruby function returns a hash informing the action component what to do.
00:15:20.550
We want to perform a post request to this path, which is just a Rails route.
00:15:27.240
If it succeeds, we want to emit this event. If it fails, we want to submit this event.
00:15:34.790
This is the event configuration. The action expects to visualize the action.
00:15:41.550
We could actually put any component here, but we decide to place a button with the text 'Click Me'.
00:15:49.240
So that's why you saw 'Click Me,' which obviously performs post requests.
00:15:55.860
Now, what happens after I clicked it will be the re-rendering of this part of the UI, showing the state string.
00:16:02.899
This occurs because I told this part of the UI to asynchronously re-render if an event is received.
00:16:08.750
We saw that the event is emitted if the action succeeded.
00:16:15.500
So, obviously, the controller behind this succeeded, allowing the event to be emitted.
00:16:22.350
The component visualizes this state string that gets pre-rendered.
00:16:29.260
We do something similar, but with a different approach on this segment of the UI.
00:16:35.670
There’s also a swing component, but now we declare it to show on this event.
00:16:41.610
It will hide after two thousand milliseconds.
00:16:48.950
This is why we could see the notification for two seconds after the action succeeded.
00:16:55.880
This leads to dynamic feedback, which we describe with a few lines of Ruby.
00:17:02.900
No JavaScript is involved in this process.
00:17:09.090
This is also a classic requirement for a dynamic user interface.
00:17:16.290
We want to respond dynamically to back-end reactions.
00:17:23.020
If the action would have failed, we would have seen the notification appearing for two seconds.
00:17:30.360
This is a new concept we just introduced. Any questions up to here?
00:17:36.480
Yes, please wait.
00:17:43.640
I'm just wondering what 'pg' stands for?
00:17:50.180
Oh, sorry. That's a paragraph tag because, in HTML, it's just 'p'.
00:17:57.810
But in Ruby, we couldn't use that directly.
00:18:02.430
So we used 'pg.' Sorry for that! We implement around twenty classic HTML tags, including div, ul, li, table, and spans.
00:18:09.710
PG corresponds to a paragraph tag.
00:18:14.670
Does the event system support more data payload in the event?
00:18:22.900
Yes, it does, but I think I can’t cover it right now.
00:18:30.440
But it is fully supported.
00:18:36.760
I think I have to hurry up; I have ten minutes left, and I'd like to show you much more.
00:18:43.300
Now it’s going to become more interesting. We have a classic requirement: user input.
00:18:50.090
Let's see what happens here. Hello!
00:18:56.170
This was done without a page reload, and part of the UI is re-rendered.
00:19:02.770
I submitted this form using my return key. I'll try to input that again.
00:19:09.150
Oh, it's not working! I see a notification, but then it disappears.
00:19:15.670
You can imagine what that was.
00:19:18.330
The reason is I have a model with validations for title presence and uniqueness.
00:19:25.220
Of course, I tried to create the same instance of the dummy model with the same title.
00:19:31.730
Active Record was unhappy about that, and the validation error messages were dynamically included in the UI.
00:19:38.440
Let's examine how this is implemented because it's another classic requirement.
00:19:45.300
We have again our page prepared, representing a new instance of the dummy model for our form.
00:19:51.700
We have some headings here, and now we focus on a form component.
00:20:00.700
It makes a component component, and it's configured again.
00:20:07.640
This configuration is stored in this method.
00:20:14.160
The form for the dummy model instance specifies what to do.
00:20:20.020
It should perform a post against this path with the input.
00:20:26.830
Similar to the action component, it expects success and failure events.
00:20:33.480
We tell the form that it should ask for the title, mark it as text, and set the placeholder.
00:20:39.820
We make it need a paragraph for spacing, but I don’t want to decide anything here.
00:20:47.050
Finally, for form submission, we want to visualize this action as a button.
00:20:54.240
This is what we see here: an input button.
00:21:00.740
Now, Mate Stack performs the magic with validation from Active Record.
00:21:05.770
Since it wasn’t unique, we see our validation error in the UI.
00:21:12.030
This is just a form input.
00:21:18.810
We have a list that displays each dummy model title for this iteration.
00:21:24.280
This is paired with a sink that reacts on the form's success event.
00:21:31.030
This is why this part is re-rendered after successfully submitting the form with a new dummy model included.
00:21:37.480
Just one more thing here, and then I’ll take some questions.
00:21:44.220
On the right side, we see page five, and on the left side, there's still page four.
00:21:50.640
Let's take a look at this part of the UI.
00:21:57.760
There are two different browser sessions, and there are some broadcasters involved.
00:22:05.740
So, Action Cable is involved. The great part is that it's very easy to implement a reactive user interface.
00:22:12.590
Let's check out page five. We see some headings and another component.
00:22:19.220
Again, this is a swing component that just displays a list of dummy models.
00:22:25.850
We instruct the sync component to rerender upon receiving an event.
00:22:34.060
It's a sync rerender based on an event, and no JavaScript is involved.
00:22:41.410
The only thing we need to manage is creating a form.
00:22:47.520
We create a form action with our parameters. Everything is classic Rails.
00:22:55.120
If there's an error, we respond with an error code. If not, we broadcast that the model was created.
00:23:00.440
This is the event that sync was waiting for to render.
00:23:08.059
At the moment, we can broadcast this to a specific channel.
00:23:15.860
That’s it; it's achievable with no JavaScript involved.
00:23:22.500
We are now looking at a WebSockets-based user interface.
00:23:28.650
Now, that's hopefully nice!
00:23:35.170
Wait a second; I need to address this.
00:23:40.640
We just saw Mate Stack utilizing components in action.
00:23:47.160
This library is well documented and tested to show you how to utilize its configuration.
00:23:55.210
If this isn't enough, you might want to create your own components.
00:24:02.690
I'm not going to go into detail about that now, but you can create your own custom components.
00:24:11.760
Mate Stack is based on UJS, so it abstracts UJS and Rails communication.
00:24:19.800
As a result, Mate Stack comes with a lot of UJS under the hood.
00:24:26.200
If you want to extend Mate Stack, you should write a Vue.js component.
00:24:32.100
Place it next to the core components.
00:24:38.180
Let’s quickly look at the sixth page, showing core components in action.
00:24:46.070
We have a heading core component and a custom demo component.
00:24:53.290
Remember: 'custom' is the namespace you need to create your own components.
00:25:00.270
The custom demo component uses Mate Stack's Ruby templating.
00:25:08.230
You simply add Ruby and Vue.js directives.
00:25:15.080
Here’s how your custom component will look.
00:25:22.220
It's still a classic UJS component.
00:25:28.930
If you click this button, it triggers an API call.
00:25:36.640
It is just classic Vue.js—nothing too fancy.
00:25:42.480
It just iterates through the received data.
00:25:48.860
This is how you could extend Mate Stack. There are really no limits!
00:25:58.220
However, the intention was that around 80 to 90 percent of classic web-driven data-driven UIs.
00:26:05.520
They can be orchestrated using these core components.
00:26:12.740
For highly specific behaviors, you simply create your own components.
00:26:18.760
Place them next to all the core components without making a mess.
00:26:29.480
In our opinion, it’s well architecture overall.
00:26:35.920
Now, you might ask how this connects through routes to controllers.
00:26:43.350
You just use classic routes—there's nothing different here.
00:26:49.790
First page, second page, whatever. You construct your controllers as you wish.
00:26:55.679
You have your actions, and you put this helper function in your class.
00:27:03.020
This tells the Rails action to use the Mate Stack class to render the result.
00:27:09.190
That’s how everything is interconnected.
00:27:15.370
We don’t touch anything else from Rails because we love Rails.
00:27:20.680
We wanted the option to add a new view layer on top of everything else Rails has to offer.
00:27:27.930
You can do this progressively, action by action, deciding whether you want to respond with a Mate Stack page.
00:27:36.320
That's it for now! Any questions are welcome.
00:27:43.480
Actually, it's 3 AM, so maybe we can have just one or two questions.
00:27:49.570
Do you have any benchmarks for how fast it renders pages in comparison with ERB or Slim?
00:27:55.260
As of now, it’s slower. We don't have benchmarks yet.
00:28:02.490
So far, we primarily focused on creating a working concept and plan to optimize it in the future.
00:28:09.340
We'll look into server-side caching and performance optimizations.
00:28:15.590
In many applications, client budget is the crucial factor rather than performance.
00:28:21.790
But we want to optimize performance as well. Thank you!
00:28:30.060
Which parts of Trailblazer are you using?
00:28:38.920
Unfortunately, you don’t directly touch that.
00:28:45.780
Trailblazer cells are very effective but sometimes too complicated.
00:28:54.820
We want to offer a much easier approach.
00:29:02.180
Finally, just a quick survey: Who here is interested in using this approach?
00:29:10.480
Wow, thank you very much! This is encouraging!
00:29:16.009
If you like what you saw, please visit GitHub and give us a star.
00:29:23.640
Look for Base Mate or Mate Stack; it's open source, so try it out.
00:29:31.149
Feel free to create issues; it's not perfect yet version 0.6.