I haven't said anything yet.
All right.
Good afternoon, everybody.
This is a front-end journey back to Rails, or how I learned to stop worrying and love
the hot wire.
This is a story of how I strayed really, really far from what you'd call vanilla Rails as
far as building new eyes goes.
I got slightly fed up and then came back, discovered that it had changed a lot, and
was really impressed with what I saw, and now I love it.
So, a bit of a backstory.
I discovered it would be on Rails in 2010, just as V3 had come out.
I happily avoided the V2 merb curve-offal, if anybody remembers.
I started working professionally in Rails in 2012 and in the last, what is this now,
14 years?
No, 12 years, sorry.
But it must.
I've worked in very different contexts, agency as a freelance, and now in a product company,
which is called NodalView, where we help real estate professionals become even better real
estate professionals with a lot of digital tools.
In my spare time, I play table top RPGs a lot.
I mentioned it one because it's a hobby that also lends itself to potentially infinite
complexity, and also because it will be relevant later for the demo I'm going to show you,
because it is about managing the infinite complexity of playing table top RPGs.
So, Rails.
Across the years, Rails, at least the front-end part of Rails, has changed a lot.
We've gone through a lot of iterations of trying stuff, following the front-end guys,
importing technologies, trying them, and then changing completely 18 months later.
We could say it's been somewhat chaotic.
So we've had a few attempts.
Like, please raise your hand if you felt five of these across your career.
All right, yes.
All of them keep your hand up.
All right.
Yeah, so this is pretty much the trajectory that I followed, maybe not quite all of them,
or maybe yes.
I'm not sure anymore.
It's a blur, really.
And after all of this, so circa 2015, 2016, I kind of settled with React as a choice for
front-end in a Rails app.
And it started relatively soft, like small bits of React, small React component, loading
a small tree in a page that still Rails.
But that did not last long.
Quickly gone to entire page.
And then, well, we're loading the data and then rendering a Rails view and then rendering
React again.
So, might as well fetch the data directly from React.
That would be easier.
And we tried with REST and you know what happened.
When what happens when you try to do an API with REST, lots and lots and lots of controllers.
So there might be something simpler.
And that's when GraphQL revealed itself.
Brings also a lot of complexity.
Anyone using GraphQL professionally right now?
Yeah.
Well, we're still using Rails routing.
We're still using Rails a little bit.
Might as well.
So we introduced ReactRouter, client-side routing in one shape or form.
And we're straying further and further away from React until we're kind of managing two
applications in a single code base.
And it's got some upsides.
And really good.
It gives us excellent UI fidelity, as we like to say.
It's really good for delighting users and clients.
It's really what we want as a result.
But it comes at a huge cost.
It essentially means you need to know two jobs if you need to shape a feature.
And around that time, I tried looking at ways to make that easier.
And this was also the era where React meta frameworks came.
Started coming out.
One of them was and still is.
Next.js, which is kind of similar to Rails.
It's very opinionated.
It's got a lot of defaults.
It does a lot of things for you.
It does a lot of great stuff.
But it doesn't really solve the problem.
We're still managing two stacks at once.
We still need to have people that are very proficient in either or Rails or React or whatever
framework we're using.
Or both, ideally, if you want to be efficient about it.
And I still felt a bit torn apart in the one job that I like to do well.
I'm doing two jobs slightly less well.
So we're now around the beginning of last year.
And it's time for a choice.
I don't feel as a developer I can keep on like this.
Having one foot in the Rails world and Ruby world and the other foot in the JS world,
it's very uncomfortable.
So I made a decision.
I was going to try one or the other, but not both at the same time.
And since I'm a very optimistic person, I tried the least likely candidate first.
So I tried to build an application, an entire full stack application using only Next.js.
No backend, no API, no a lot of stuff.
And I quickly realized that it was going to be harder than I thought.
I was missing a lot of things daily, constantly.
I hadn't realized how much Rails and Ruby gave me until I started generally missing it.
And there wasn't a single day where I wasn't telling myself, yeah, I'm going to need Rails
to do this at some point.
And that's through.
It wasn't a happy experience, to be honest.
As you can see on my screen.
I was missing a lot of features.
Next.js doesn't have an ORM or we have ActiveRecord.
It's not that it has a bad one.
It doesn't have one altogether.
Doesn't do background jobs, doesn't do file uploads by default.
Deploy anywhere.
It's kind of a joke.
You can deploy your Next.js application everywhere, but you should really deploy it on Versailles
if you want to make it good.
And also it's not in Ruby.
This is half a joke and also not.
When you've been writing Ruby for more than 10 years, you don't realize how much you're
going to miss the methods in Enumerable until you don't have them.
And that's the same thing for a lot of cool APIs.
When I was doing that, the React ecosystem was changing a lot very quickly.
Rails had historically been the framework for building single page apps until it wasn't.
And the industry took a nosedive into the complete opposite direction with something
that they called server components.
It's really hard to, it's a talk in itself.
I'm not going to go into details.
So now the code is written on the server, then it executes again on the client, but
not all of it, just the one you mark use server.
But the one you mark use client is only on the client, but not really.
So it's complex.
And it started getting, first of all, very exhausting, but also kind of weird.
I don't know if you can read the content of this React component.
And I don't know.
For everybody at the back end at home, this is an SQL query right in the middle of the
React component.
I'm not sure how it makes me feel, but it's not good.
So second attempt.
Yeah, kind of obvious and high-signed.
So I was still doing Rails at work every day, so I was constantly reminded of how much
better it was.
So this time I tried, okay, I'm going to do it with only Rails.
Time to see what's new in the frontend part of Rails.
And the goal was, I wanted to use Rails, like all of Rails, without sacrificing either the
quality of the UI, the quality of the experience for the user, and the quality of the experience
for me.
So that means that I still want all that.
So everything that I had gotten used to from the few years of React, obviously components,
but all the cool features, and all the, more importantly, all the UI features that a user
would expect.
I can't legitimately tell a user, well, you know, it used to be good, but now I'm doing
only Rails, so welcome back to 2010.
That wouldn't quite work.
So can I, could I actually do all of that?
Let's find out.
Components.
Components used to not be a part of Rails, really, you could get a lot done with Partials,
but now they are.
There are two libraries that do that pretty well.
The first one is your component that I will not be talking about.
The second is Flex with a pH that I will be using in this talk and in my applications.
So this Ruby object that is a component that will render bit of HTML at some point the
same way a ERB partial would, except it looks more like a component.
If you squint a lot, you might see a React component there.
It's got a prop and it's got a render method.
And that's the real basics of it.
The major difference is that it's a plain old Ruby object.
So this is already big for me, at least.
It means two things.
It means I cannot forget five years of best practices of designing and components.
That also means that I can pretty much import one-to-one components that I've designed in
React.
That means that again, it's a plain Ruby object, so I can do any kind of Ruby in there.
This is also the good place for what used to be a decorator object or a presenter object
in older applications.
In the same way that you can render a component partial, sorry, in your controller, you can
render that component that I just showed you.
Same way that we'll do exactly what you think it does.
Except that this would be an entire view.
So you don't even have to do...
You don't even have to do ERB for your views.
You don't have to do ERB for your layouts.
You don't have to do ERB at all, which is pretty cool.
Because I don't know about you, but I don't really like ERB.
It's really got a really clunky syntax, not a fan.
So we can go a little bit further with components.
You can add slots, which would allow you to define a skeleton for something that takes
children like you would in React and call them later with a block.
This would be...
This represents a pop-over menu.
It's got a trigger and it's got a content that will be revealed once you click on it.
There will be a demo in just a minute.
But what about interactivity?
This brings us to the first part of what Rails now provides as default tools.
It's called stimulus.
And it's a very, very thin wrapper around a DOM object with a few lifecycle methods
and event antlers.
It's really, really bare bones, but it's enough.
And in that case, it's enough to give us a possibility to bind click on that trigger
and show the menu with a class and transition.
And this is what the stimulus code looks like.
Same it's got a connect method.
You might remember a component that mounts from React, if you've used React, that's the
exact same thing.
And a few methods that do what a pop-over does, show clean, show high clean, that's not really
complicated.
I think this is the only place in the application that I'm going to show you that actually uses
developer level JavaScript.
The rest of it is either turbo or stimulus.
Little bonus.
I don't know if you can see it, but first line of the connect method, there's a use
click outside.
If you're missing hooks from React, don't worry.
They're still there.
There are hooks libraries for stimulus as well.
So you can mix and match regular behavior in your stimulus components.
All right, time for a little demo of what I just said.
How do I get out of this?
I won't see it here.
So this is the application that I'm using to manage my table top RPG tables.
And this is the pop-over that I just showed you with just a few lines of stimulus.
And this is a normal pop-over is the point.
It's just the same as you would expect.
Coming back to the talk.
There we go.
The second part that I really, really wanted to keep because I just got it from React is
suspense.
You might remember suspense as the thing that loads your bits of JavaScript at the time
that they're needed.
But it had recently evolved, allowing you to put some kind of network request in a component
and it would suspend, that's the name, until the network had finished and then it would
show the component with the data in it and would display a fallback in the meantime.
Like some sort of loading screen, spinners, Keletun or something.
And turns out that this is really, really easy to do in Rails now.
This is what it looks like.
So this is the moment where we introduced the second really important part of modern front-end
in Rails, Turbo and more specifically Turbo Frames.
Remember iFrame from the 90s?
This is similar but kind of better.
So what we're doing here is calling a Turbo Frame, giving it a name and giving it a source
which is another route in your application.
Sorry.
When the page containing the code on the top is going to be loaded, it's going to load
the second page in the background.
See if there's a frame with the same exact name on the other page and then show that.
That's the part of the page that's got the frame with the same name.
And you can still put your fallback in there in a block within your frame.
It will appear until it's loaded.
I'm going to show you what that does.
So this is the frame on the other page.
Major difference with React.
This other page can absolutely be a real page that's got its own use.
That reduces a lot of duplication.
I'm going to show you.
It's going to be easier to understand.
With a demo I need to get out of there again.
There we go.
So this is the frame that I just showed you.
No, this is not.
I'm lying.
This is the frame that I just showed you which is loading the list of the parties that belong
to.
But the list of the parties that belong to is also here.
This is the same exact same code, same controller, no duplication.
If I refresh the page, you see it.
Just flash the loading screen and then load it.
So that's how you do suspense in modern Rails.
List one, inline forms.
This is one of the big reasons why you would use frontend framework like React to do stuff.
Same general ID.
You define a turbo frame.
This one doesn't have a source because it's not fetching a page right just yet.
You have a link that explicitly points to that frame.
So when you click on that link, instead of doing a full page reload and going to a page
like a link would normally do, it's going to see if there's a content with the same
frame name on the other page you're going to and then populate the content of that frame
on your current page with that.
And then you have an inline form.
From the form page itself, it's mostly, very mostly normal Rails form.
The UI.form that you see here just delegates to a form for that some standard Rails with
the slight change of giving it a turbo action and a turbo frame.
Caveat, I'm using the still unreleased new version of Turbo, Turbo 8 that just got dated
to RC yesterday.
So this is very fresh.
It might be released this week.
I hope.
I really hope.
It's really cool.
So if it's a new record, I want to refresh the entire page.
I'm going to create a full navigation with advance.
If it's not a new record, if I'm editing, again, still with an inline form, I will just replace
the content.
Since I'm doing full navigation for the create action, I'm going to target the turbo frame
at the top, which means the entire page.
Otherwise, I will just refresh the frame I'm constrained into.
And I want to stress that the controller is like the most vanilla controller.
There's no magic here.
This is just a normal Rails controller the same as 10 years ago, except maybe giving
it a status if it fits.
That's now needed.
Demo.
I think this is what I'm going to do here.
So this is the link that I showed you before.
Creates a form that I can barely see.
Thanks, dark mode.
I want to say test.
There we go.
Test, test, yes.
Save.
Boom.
It's there.
It's a thing.
And now I can edit it.
Test one.
Super creative.
And it's there.
And it was very in line and very cool.
That's inline forms.
Loading states.
If you were paying attention, you might have seen that when I was submitting these forms,
the button changed.
You got grayed out.
You got disabled.
And the text changed.
The first part of that, I think disabled to buttons that are not doing a get action and
all of the submit inputs, is done automatically by default by Turbo.
And if you want to get a little fancy with it, you can add the Turbo submit with, that's
a mouthful, arguments to that button and it will change the text while it is loading.
That's also pretty cool.
I think, do you want to see it again?
Yes.
All right.
I'm running a little bit short on time.
Where am I now?
There we go.
So I'm just going to do an edit one more time.
So therefore test two.
Look at the save button, please.
There we go.
All right.
No, you stay.
This is not for you.
All right.
So that was demo.
Okay.
This is the pool one.
So all these really fast inline updates that I just showed you.
Well, that's all what I'm good.
That's easy to do in any technology really.
What would be really cool is if when you update that post, everybody else that's on that
page, like your party members in my demo application, would see the result immediately.
And when you say that, that seems like it's a hard thing to implement.
And if you've done it in another language or framework, you might think or have learned
that it's hard to implement.
No, it's not.
Main part is you need to add that single keyword broadcast refreshes to the model that should
refresh on the page that should be refreshed.
You just add turbo stream from and the object.
And the special case at the top, which I did in the wrong order I realized now, is a special
case for when you're creating a record because you can't subscribe to record that doesn't
exist yet, that doesn't really work.
So the trick is to subscribe to a parent record and touch it when you create an as many association.
And that's it.
That's the whole thing.
It's done.
It's all refreshing.
I'm just going to show you this one I'm really excited about.
Again, I did that on the wrong space.
There we go.
So I had prepared a thing so you can see it.
So test number two, I'm on the deleted.
By the way, fancy confirm confirm dialogues also provided by turbo boom.
It's gone.
It's gone on the other side too.
Thank you.
I didn't make it, but I'm raising awareness.
Let's see.
Again, wrong space.
This is hard.
All right demo.
Let's go back to playing.
There we go.
So yeah, if I'm honest, I think that covers about 80 to 90% of the common use cases of UI
fidelity that you would ask in an application.
And those tools that I've briefly gone over are versatile enough to do a lot more and
they're getting a lot better as time goes.
So yeah, for me at least it is mission accomplished.
But wait, there's more.
No, I like there's less.
All of these things that I just showed you, they mean a lot of a lot fewer things to do
to get to the same result.
Meaning no more internal API is no more GraphQL no more 5000 rest controllers and J builders
and you know, no more playing around with local state, at least very, very, very little,
if not at all.
No more duplicated logic across to half stacks.
No more interminable asset compilations that take all of your GitHub action guillible time.
By the way, plugging bun as a replacement for yarn or PNPM, bun is very cool.
No more building and also hiring expertise in two different frameworks to do a thing.
That's pretty cool.
Yeah, lot, lot, lot less things to do.
So of course this is a game of trade-offs.
This is not a perfect solution.
It's not as native like, as super cool as doing a full front-end framework.
But on the other hand, it's sticking with the framework default a lot more.
You get stuff done way quickly and you can realistically get stuff done alone if you're a solo developer,
if you're just starting out, or if you want more bang for your hiring buck.
But all of that means nothing.
That means a lot.
And that's the end of the talk.
We have a little bit of time for questions.
Yeah.
Yeah, the live refresh result, the live reload.
Yeah.
What's that behind the scenes?
Is it WebSockets?
Yeah, it's WebSockets.
It's all action cables, WebSockets.
The question was, sorry, what library is that for the refresh?
And it is in fact WebSockets.
It's all action cable under the hood using the action cable from Rails.
Yeah.
I have also a comment, because I've also been looking into the data of the new turbo.
And the refreshes does work well, but it's very important to also use a data turbo permanent on forms,
because if you don't and you refresh all our users, then there's a full context.
Yeah.
Okay.
So, full context, there are caveats, like you mentioned,
especially when you have JS powered elements on the page, like a Tricks editor, like I just showed you.
If you want to preserve their state, you need to do something about it.
Yeah, that's right.
Anyone else?
Yeah.
Do you consider a great solution, stand-on, angular or react application with RESTful APIs?
Or, as you said, it's too hard.
It's really too...
So the question...
Yeah.
...personally love the syntax of the component, the Rails component.
Okay.
So the question is, would I still consider full front-end applications like React or Angular?
Yes, but we have some at work.
We have a big one at work, for example, and I'm certainly not going to throw that one away.
But if I were starting a new application with...
I did, and if it was a solo project or a very small team or an early-stage startup or just for fun, I'd definitely use this.
And I wouldn't invest in a full front-end framework unless there was, A, a lot of money behind it and the real explicit use case for it now.
Yeah.
How hard would you say it is to migrate from the hellhole of having two different stacks to something like this?
Can you do it partially or do you have at some point to...
You could do it partially.
The question was, sorry.
How hard it is to migrate from an existing front-end application to this?
The answer is you can do it step-by-step, replacing maybe some routes first, maybe your admin panel if you want to be in a safe space.
And you can probably do it route-by-route, doing something like routing at the end-to-next level or something like this.
And it doesn't have to be one or the other.
I think... Yeah, there's one more.
What's the best source of documentation for, for example, the broadcast...
Oh yeah, Jesus.
Yeah.
Thanks for the question.
Because some things use... Sometimes it's about rails, but sometimes it's about turbo.
Yeah.
Sometimes it's confusing where to go and look at that explicit call.
I didn't know about broadcast repression.
Yeah, it's new. It's still beta.
So it's not...
It could be in the turbo documentation.
It's in turbo rails. It's provided by the Turbo Rails gem.
So the question was, what's the best source of documentation that I've compiled a little bit, which contains also links that I've compiled a lot more,
and expect all of that to change in the very near future, sorry, like I mentioned, a big solid upgrade is coming probably next week to the main driver of this.
Last one.
Do you have any experience with the Strada and the...
No. I voluntarily did not... Do I have experience with Strada?
Strada is the third wheel in turbo stimulus and the whole package of hot wire,
and Strada is used to bridge native applications, native application skeletons with web views that are using the other two.
I have no experience with it. That's why I didn't mention doing this talk.
And I think that's it. Thank you very much for listening.