Modal Title
DevOps Tools / Frontend Development / Software Development

Turbocharging Ruby on Rails with ‘HTML Over the Wire’

Tutorial showing how to use the modern HTML Over the Wire — and Hotwire specifically — approach with the classic Ruby on Rails framework.
Jul 23rd, 2022 5:00am by
Featued image for: Turbocharging Ruby on Rails with ‘HTML Over the Wire’
Lead image via Shutterstock.

Ruby was my first love, my first language was C, and now I go steady with C#. This is a typical romantic journey for most developers; falling for a shiny new methodology, only to flirt with a statically typed language later. But there’s one thing I have been consistent with: I don’t want to write JavaScript if I don’t have to.

Now, as a pragmatic developer, I recognize why I might need JavaScript, but I’d always prefer to be in the more comfortable confines of a bigger language. Since the birth of node.js, there have been plenty of devs who are happy to use JavaScript exclusively — for both client and server. And admittedly, I did like the control that media queries gave me with responsive web design.

I’ve always thought Ruby on Rails was a little easier to manage because it was “opinionated” — even if it was a little too keen to push you into a database. So I was intrigued by the idea of “HTML Over the Wire”; and Hotwire specifically. It seems to give you JavaScript-like abilities without actually having to write any. So I thought it might be time to fire up a Rails project and see how that went.

Installing Rails (Again)

So, let’s start with a simple Rails installation. We just want a form and response. I’ll assume that you are comfortable with what Rails is and its basic tenets, but maybe (like me) you haven’t done all this stuff for a while. So here’s what I’ll do:

  • I won’t use a database;
  • I’ll try using a generator, so I don’t have to remember all the files needed.

I have an rvm (Ruby enVironment Management), so let’s try to install a new ruby to match what we need for Rails. Naturally, whatever Ruby I did have wasn’t high enough:


Then the important stuff:


That gave me 35 gems and documentation.


Ok, so let’s ask the generator for a skeleton application, with no tests or active record.


At least we have enough to throw something immediately on the screen. As I demonstrated with Sinatra, the current favored server is called Puma. So on my Mac, we can wander into the app directory and start a server with Puma:


And at http://localhost:3000 we see the default Rails page. I can already see some Hotwire things in the Gemfile (there is a “turbo-rails” gem), so perhaps we don’t need to do anything further for that.

We want a simple form, like a sign-up page, and then update it after submission. I used to use a Flash Message for this in the past. So in a Model/View/Controller world, we want a user model, then a form for our “new user” view, and finally a registrations controller. No, I haven’t written any of these things yet.

Fortunately, despite not using Rails recently, my old friend the “routes.rb” file still exists. A route is how we describe our internal architecture in good REST fashion. So I associate the URL GET request “/sign_up” with a new registration, and it’s POST response appropriately too.


OK, so we better make a registrations_controller. Remember, the Rails world is very opinionated, so stick to the mantra and use the words and phrases as expected. We are already being difficult by not having a database!

But first, a quick User model. Note that because I ditched the database, we are using ActiveModel to persuade Rails we are good citizens. So in “app/models/user.rb” we have:


And a quick RegistrationsController in “app/controllers/registrations_controller.rb”:


And this minimal view in “app/views/registrations/new.erb.html”


We get this blessed result in the browser:

OK, that is cool but we need a more fulsome form. After all we need something for Hotwire to do.

Now, this isn’t a post about the multitude of ways you can get a screen to look nice, but I’ve squeezed a bit of juice out of Rails and HTML, so the form looks alright without having to do anything much in CSS. For a real project, you would probably want to do the opposite.

The Rails smart magic works via “form_for”, between the ERB tags, which looks at the model (i.e. user.rb) and riffs on that. It even deduces that “Create User” would be a good default for the submit button text. This is what you are paying for when using Rails.

Here is the nicer view:


Note the URL override to send the response to the sign_up path we have made in routes. I’ve identified the fields, as will need that shortly. The rest is just Rails and HTML.

Just to make it a little cleaner, I have added a simplistic CSS in “app/assets/stylesheets/application.css”:


This all gives us this:

Getting Hotwire Involved

OK, wonderful, but this post is about Hotwire. Normally we would have to redraw a new page here, or use a little Flash Message to somehow confirm that a user has been created. But what Hotwire in its Turbo Stream mode gives us is a chance to replace a section of code in response to an action. This is done in AJAX so no screen drawing is needed, but also it is done in a nice Railsy way. A Railsway. Take a look at “app/views/registrations/submit.turbo_stream.erb”:


Firstly, note the nomenclature of the filename. The rest is kind of simple; in this case we replace the identified div with some simple HTML.

I added the create method to the “app/controllers/registrations_controller.rb”:


I clearly haven’t quite got the variable use right here: the @user in the create that reads the incoming parameters is the important thing though.

Here is the page after you create a user:

So, to summarise the behavior and flow:

  1. We relate the GET request sign_up page to the registration controller’s new method in “routes.rb”.
  2. Rails knows to relate the registrations new method to the correct registrations view “new.html.erb”, where the form is.
  3. The form is displayed, based on the “user.rb” model.
  4. The button on the form sends a POST request to sign_up.
  5. We related the POST sign_up to the controller’s create method. This directs rails to render the submit view.
  6. Turbo looks for the “submit.turbo_stream.erb”, and makes the replacements asked for.
  7. The result is no page redrawing.

While I took a bit of time to grok how Rails is currently set up, and I almost certainly haven’t used it in the official way, it is still very easy to play around and see the results. However, familiarity with HTML and CSS are still necessary — even if we can briefly ignore our JavaScript overlords.

Group Created with Sketch.
THE NEW STACK UPDATE A newsletter digest of the week’s most important stories & analyses.