Instantly Write Turbo-Rails Scaffold for Admin Views + More
Turbo-Rails is a bold new vision for Ruby on Rails. It is based on an old concept from the early days of computing, dating back to the 1970s, called “dumb terminals.” This means that the computer screen you use is for display only. In the ‘dumb terminal’ world, the majority of the computing will happen in the cloud and the terminal you use will be ‘dumb,’ or not contain a lot of heavy processing logic.
Turbo-Rails is the opposite of that idea. In Turbo-Rails, you’ll keep your business and display logic on the server, and treat the browser as a terminal that is there to display your UI only— it is ‘dumb.’ Whether or not Turbo-Rails will rival the new kids on the block will remain to be seen, but it sure is fast.
These days, I think most of the process of building a great app involves user feedback, product-market fit, and iterating to make sure your users actually want what you’re building. The power of Rails lies in ActiveRecord and migrations, and thus it is an ideal tool for putting together prototypes quickly. The problem is, Rails has its own idiosyncratic syntaxes that make getting started challenging for those curious about this old framework. Do I start with Turbolinks or Turbo Rails or just plain page reload interactions? How about I treat Rails as the API-only and build my own frontend? Should I use ActiveRecord’s relationships, even knowing that instantiating (loading into memory) a lot of Rails objects can be slow? Will Ruby 3 really be 3 times as fast as Matz promised?
The problem presented is that there are almost too many choices for people who just want to build a basic app today.
As the CEO, entrepreneur, product owner, or visionary, your job is to map your users’ mental models. From there, the programmer will take those user mental models and map them onto code, objects, interfaces, or tuples (database records). Then comes the marriage of these to the interfaces, screens, and interactions that will happen for your app. Perhaps you start in Rails quickly and get lost in specific syntax, style, or architecture decisions to do basic things. Frustratingly, you are attracted to Rails’ simplicity but have a hard time with its recherché parts.
Meet Hot Glue
This gem, Hot Glue, is a rapid application prototype builder for Rails. It will take your existing models and build you quick dashboards using Turbo Rails. It assumes you know the basics of Rails — MVC, routes, etc — and want to build a Create-Read-Update-Delete (CRUD) set of operations on an object in your database. It handily comes with a LIST page with pagination and does all of its operations as Edit-in-Place. This means the user never leaves the page. It gives you a simple, lego-like set of building blocks to formulate standard-looking dashboards. It stays within those bounds and tries to do what it does well and nothing else.
This tutorial will introduce you to Hot Glue by walking you through five separate examples. Each of the examples demonstrates a different part of Hot Glue, and by the end, you should have an understanding of how to use it.
If you are not yet familiar with Rails MVC (Model-View-Controller) or Rails routes, you should start with a basic Rails tutorial or the Rails guides.
Hot Glue has only 1 page of documentation — the README itself — which is the same as its Github home, here.
For this tutorial, you will need to scroll to the section marked “Getting Started” in the this README document, and follow allow there. I will reference those steps below briefly but not repeat all of the details.
Remember, start with “Getting Started” in the README. As you go through each step, always remember to examine and check in your code. That way you can easily see and understand what each step does.
First, if you’re on Rails 6, complete the LEGACY SETUP STEPS first.
The very last thing to consider is Devise and authentication, but that is not necessary for Example 1.
Example 2 specifically covers how to install Devise and shows how access control works with your logged-in user.
Example 1: Books & Authors
The Books & Authors example is the simplest of all of the examples: It contains only two tables (books & auth, and two scaffoldings. You will need to go through all of the setup steps in “Getting Started” above, except Step 9. For this example, we will use –god (or –gd) controllers, which means that they are like admin interfaces: By default, they will be able to create/read/update/delete all records on the tables we are constructing.
Remember, only use Gd controllers when you also have some kind of admin authentication. We will cover that example later; for Example 1, the Megatron is only a demo app so it will allow any user access to both tables (no authentication).
When you make your new Rails app, make it with
rails new BooksAndAuthors --database=postgresql
Then go through “Getting Started” above (except Step 9).
(Somewhere along the way during the setup make sure you
rails db:create and
rails db:migrate to get your schema started.)
Next, we’ll make two models & migrations using the Rails built-in model generators:
rails generate model Author name:string
Take a look at the 4 files that Rails has created or you:
This is a normal Rails migration that should look familiar. If it doesn’t, take a look at the Rails guide for migrations.
class CreateAuthors < ActiveRecord::Migration[6.1]
create_table :authors do |t|
All we’re doing is creating a table of Authors who have a name. (The t.timestamps tells Rails to create both an updated_at and created_at timestamp for this table.)
rails db:migrate to create the Authors table.
Before we get to building the scaffolding, let’s keep going and build out our Books table. Take a note that this Books table is just a small pretend part of a demo app. Its purpose is to demonstrate one of each type of field so you can see the all the field types in action.
rails generate model Book name:string author_id:integer blurb:string long_description:text cost:float how_many_printed:integer approved_at:datetime release_on:date time_of_day:time selected:boolean genre:enum
Don’t migrate the database again — YET!
We will need to fix the enum field before you can run the migration.
Now go ahead and find the migration file itself and edit it to add the enums.
Fix the Migration
In the Megatrons create migration, add code shown in orange below:
class CreateBooks < ActiveRecord::Migration[6.1] def change create_enum "genres", %w[Fiction Nonfiction Biography Science_Fiction Mystery] create_table :books do |t| t.string :name t.integer :author_id t.string :blurb t.text :long_description t.float :cost t.integer :how_many_printed t.datetime :approved_at t.date :release_on t.time :time_of_day t.boolean :selected t.enum :genre, as: :genres t.timestamps end end end
Now you can run
Add the same Enum to the Model Books
Open app/models/book.rb and add this code:
class Book < ApplicationRecord include PGEnum(genres: %w[Fiction Nonfiction Mystery Romance Novel]) end
Now, while we’re in here, we’ll hook up our Books to Authors. As you might have guessed, Books belong_to an
:author, and an Author has_many
:books. If you aren’t familiar with Rails Active Record relationships, check out the Rails guide here.
class Book < ApplicationRecord include PGEmum(genres: %w[Fiction Nonfiction Mystery Romance Novel]) belongs_to :author end
class Author < ApplicationRecord has_many :books end
Finally, let’s build the scaffolding:
Here are the two Hot Glue commands we’ll need:
rails generate hot_glue:scaffold Author --gd
rails generate hot_glue:scaffold Book --gd
Run them both and see what is output:
For every scaffolding you build, Hot Glue generates up to 16 files:
|A spec file|
By design, the files that begin with underscore (_) are called partials, and they are used as sub-views of top-level views or other partials. Also by design, the top-level views (shown here with *) all expect to have instance variables made available to them (@) by the controller itself. Then, those top-level pages will in turn render lower level partials (which begin with underscores) and when they do, they pass the objects down the chain using local variables passed in-scope when the partial is rendered.
This is important because the lower-level partials (any views that are not top-level) should not reference instance variables. In most cases, the instance variables switch names from the instance variable name (
@abc) to a local variable name (
abc) when you move from the top-level views to the partials. This is by design and facilitates seamless re-use of the views using nesting.
The other thing to note is that the edit template and the new template share a single template: in Hot Glue’s case, it happens to be the _form partial.
This central partial is where both edit & new operations will be rendered from. In fact, it sort of is like a “show-edit-new” partial in that it can do any of the above.
Unlike Rails scaffolding of the past, there is no extra “show only” (non-editable state) template generated as I have found it not often useful. The _show partial displays a “show only” format of this record in list view.
You can specify field-level “show only” (non-editable) functionality— and you can easily make all of your fields “show only”.
However, there is no concept of the controller having a “show” state vs. a “edit” state. The fields that are show-only (non-editable) will display as non-editable on both the create & edit screen, and the controller will not allow those fields to be submitted.
A naive Rails approach to a “visible only” state would easily leave parameters you want to protect from hacking inside of the allow parameters list— a security flaw. If you’re a little fuzzy about when & where you want your users to view-only vs. be able to edit something, I’ve found this leads to quickly opening up field-level security flaws. For example, the user is allowed to have access to the record but they aren’t supposed to be able to update field X, but you accidentally leave field X in the allowed params list even though it doesn’t appear on the display. Hot Glue is encouraging you to think about the simple Rails code you are generating: it forces you to specify that this controller should have this access to these fields.
If you find yourself wanting to give different access in different cases, stop and listen very carefully: You probably want a new controller. One of the most common pitfalls of new Rails developers is Overloaded Controllers. Hot Glue is built to encourage you to keep making more controllers (even though at first it seems like too much code) when you want a new ‘feature’ or a new ‘function’ or a new ‘context’ or a new ‘path’ for that user for that object.
The basic architectural principal is based on Domain Context Interaction, which I recommend you read more about in Jame Coplien’s excellent book Lean Architecture. By building out many controllers you are encouraging yourself to see and identify the commonalities between them — those can be abstracted using mixes and inheritance — and discover the careful art of defining your business domain in conjunction with your code mental models.
Putting lots of operations upfront in the same controller is the enemy of this process, which is why Hot Glue encourages you to stick to the basic CRUD + list operations only for each controller and not make up your own actions.
There is one exception, and that exception is magic buttons, which are implemented as a sort of middle ground between making redundant controllers and overloading your controllers with business-specific actions. Magic buttons are buttons that submit as PATCH http verbs directly onto the existing update methods, which is correct & standard as according to the rules of REST, but instead of just updating data on the object they instead call a bang (
!) method on that object. This bang method in turn invokes or effects some kind of non-idempotent (change-making) action (for example, Activate, Release, Publish, etc) for this context interaction. For more on this topic, see the discussion in Example 6 below.
Although it may seem like Hot Glue is generating too much code, remember that code is cheap and your time is expensive. The scaffold is designed to do what it needs to do today, for the given context it was built in, but be easily disposable and not get in your way to architect the rest of your app.
Add these routes:
Rails.application.routes.draw do resources :books resources :authors end
Does it work?
For this example, I’m using the like_los_gatos theme, which is a Netflix-inspired skin for Hot Glue that features bright Red buttons and inputs & textareas with 2px rounded corners. Be sure to install a theme in Step 6 when you install Hot Glue.
It lets you create, edit and delete author records:
Now go to Go to
As you can see, out of the box Hot Glue produces views and a controller that is highly functional. In this one view, we’ve packed in a string, text field, float, integer, datetime, date, time, boolean, and enum.
Notice that for strings, Hot Glue made a simple one-line input field (like for name). For the long description, Hot Glue detected that the field on the database was type text and made the input a textarea box.
Hot Glue figured out the fields that were dates & times and datetime and output HTML5 date & time selectors.
Booleans magically appear as “Yes/No” radio buttons, and foreign keys (the
author_id) and enumerated types are turned into drop-down lists automatically.
Because Rails default belongs_to also adds a validation to the field, the author field is required to be on the books above. When you go to save a book without selecting an author, the form is re-rendered with a red error message and the field where the problem is shown in red.
- Hot Glue Tutorial 2 – Users and their Widgets
- Hot Glue Tutorial 3 – Pet Spa
- Hot Glue Tutorial 4: Human Spa
- Hot Glue Tutorial 5 – Validation
- Hot Glue Tutorial 6 – Magic Buttons
Localized Timezone Support
In order to show dates, we use a localized date display: the date & time is always shown to the user in their own date. To do this you have a few choices: (1) You can save the timezone to the user’s table, and let them set it for themselves, (2) You can show everybody the server’s date.
Option #1 – Store
timezone On the User object
We already took care of this by adding timezone to our User object.
Option #2 – Use the Server’s Timezone
If the auth object (current_user) does not respond to timezone, the Rails “system clock” will be used. The system clock’s timezone as set by the Rails app is used. This is often the timezone of the headquarter’s of the company that owns the application. (That is, if you do not know the user’s context, you simply use your own company’s context instead.)
Power of Hot Glue
Hot Glue harnesses the power of many great things about Rails:
• Turbo-Rails for fast front-end interactions
• Database migrations
• ActiveRecord associations (has_many, belongs_to, etc
• Chains of has many relationships for simple “starfish” access control
• Devise for authentication
• Bootstrap & FontAwesome to tie things together and make them look slick.
Remember, make your models first: Add limits and defaults to your database fields by modifying your migrations. Then add the relationships between the tables using standard ActiveRecord has_many, belongs_to, and has_one.
Then build the common core scaffolding & customize the views and controllers it produces.
With these powerful tools, you can build a dashboard-like app in minutes, complete with simple interface buttons that let your users accomplish most of what they’ll need. The philosophy is that you will want this dashboard as you initially introduce people to your product. The main logic of your application will likely live more in the models, service objects, and domain layer (business logic) parts of your Rails app. For this reason, you are encouraged to customize the files only lightly. (Add some verbiage or change the CSS to customize the look & feel.)
The code you build with common core is cheap and disposable. It is not very modern, but it gets the job done. It is just “good enough” to launch a sophisticated app on, but it isn’t good enough to impress your users with a really good UI.
For that, you’ll want to throw away the front-end code and replace it with a modern JS UI like React, Vue, Ember, or Angular.
By that time, Hot Glue will have already helped you build a prototype and your business logic. For admin-only screens where a full-featured dashboard is desired, building scaffold using Hot Glue is a perfect fit.