How to Create Custom Scaffold Templates in Ruby on Rails
Tags: rails, ruby, webdev, tutorial
Published: 2019-05-26 20:20:04

---
title: How to Create Custom Scaffold Templates in Ruby on Rails
published: true
tags: rails, ruby, webdev, tutorial
canonical_url: https://web-crunch.com/how-to-create-custom-scaffold-templates-in-ruby-on-rails/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/dna5dqf1gncw9hw5bier.jpg
---

Ruby on Rails is such a powerful framework. It has its own CLI of which harnesses what are known as “generators”. These generators can quickly scale up resources for your app with a few keystrokes. In this post learn how to create custom scaffold templates in Ruby on Rails


{% youtube BTW3MSkX6O0 %}

### Conventions get you far

Having made quite a few brand new Ruby on Rails apps in my time I always find the default look and feel of scaffolding out a resource a bit lackluster. By default, Rails generates a ton of files and stylesheets associated with a given model you pass on the command line when creating a new `scaffold`.

Example:

```bash
$ rails generate scaffold Post title:string body:text

```

The command above will create an entire CRUD-like concept around the `Post` model in a given rails application. To do this it generates a number of files which include everything from stylesheets to test-specific files. It also creates an Active Record migration file which will later be migrated into a database. This ultimately means a new table is born called `posts`.

This concept is a huge time saver. This is especially true if you’re just prototyping an idea or testing a theory.

### Extending conventions

Within a typical scaffold, you get an entire view folder with associated views for the restful routing that gets created.

```bash
app/views/posts/_form.html.erb
app/views/posts/edit.html.erb
app/views/posts/index.html.erb
app/views/posts/new.html.erb
app/views/posts/show.html.erb

```

Here we get the bare bones views with the logic they need to make the app work as intended. Having run so many scaffolds in my time I’ve come to realize I hate the default look and feel. Can this be changed? The answer to that is YES!

### Custom scaffold view templates

Inside your app you’ll find a `lib` directory. By default it would probably have `assets` and `tasks` folders but we need to create a new `templates` directory.

The structure ends up like the following:

```bash
lib/
-- templates
  -- erb
    -- scaffold
      --| _form.html.erb.tt
      --| edit.html.erb.tt
      --| index.html.erb.tt
      --| new.html.erb.tt
      --| show.html.erb.tt

```

The new files with `.tt` extensions may look new. That’s because they are! These are a new type of view that classify as templates. When a new scaffold is run, the framework will find these and use them to scaffold out the new views that get generated.

### Check out the index view:

```erb
<!-- lib/templates/erb/scaffold/index.html.erb.tt -->

<div class="container mx-auto my-8 px-4">
  <div class="flex justify-between items-center mb-4">
    <h1 class="h2"><%= plural_table_name.titleize %></h1>

    <%% if @<%= plural_table_name %>.exists? %>
      <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path, class: "btn btn-default" %>
    <%% end %>
  </div>

  <%% if @<%= plural_table_name %>.exists? %>
    <div class="bg-white rounded shadow">
      <table class="w-full">
        <thead>
          <tr>
<% attributes.reject(&:password_digest?).each do |attribute| -%>
            <th class="p-3 uppercase text-left text-xs text-gray-700"><%= attribute.human_name %></th>
<% end %>
            <th class="p-3 uppercase text-left text-xs text-gray-700">Actions</th>
          </tr>
        </thead>

        <tbody>
        <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
          <tr class="group border-t border-gray-400 hover:bg-gray-100">
            <% attributes.reject(&:password_digest?).each do |attribute| -%>
              <td class="p-3"><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
            <% end %>
            <td>
              <%%= link_to "View", <%= singular_table_name %>, class: "btn btn-default" %>
              <%%= link_to "Edit", edit_<%= singular_table_name %>_path(<%= singular_table_name %>), class: "btn btn-default" %>
            </td>
          </tr>
        <%% end %>
        </tbody>
      </table>
    </div>

  <%% else %>
    <div class="bg-white rounded shadow flex items-center justify-between p-8">
      <div class="flex-1 text-center">
        <p class="text-xl font-semibold mb-4">Create your first <%= singular_table_name.titleize %></p>
      <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_route_name %>_path, class: "btn btn-default" %>
      </div>
    </div>
  <%% end %>
</div>

```

A number of things to note:

- This assumes you created a new rails app using my [Kickoff Tailwind](https://github.com/justalever/kickoff_tailwind) template. The classes you see pertain to Tailwind CSS as well as some custom components that come by default when you create a new rails app using the template. I talk more about recent changes to the template [here]
(https://dev.to/justalever/latest-news-rails-6-jumpstart-pro-and-kickoff-updates-28g0).

- The `<%%` signs are new and essentially act as a templating preformatter when a scaffold gets run within the context of `erb` files.

- Inside these templates, we have access to local variables and methods like `singular_table_name` or `singular_route_name` of which are dynamic. These will get replaced with whatever resource you’re generating. In our case, it would be `post`.

### The edit view template

```erb
<!-- lib/templates/erb/scaffold/edit.html.erb.tt -->

<div class="container mx-auto my-8 px-4">
  <div class="max-w-xl mx-auto">
    <h1 class="text-2xl font-bold mb-6">Editing <%= singular_table_name.titleize %></h1>

    <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
  </div>
</div>

```

### The new view template

```erb
<!-- lib/templates/erb/scaffold/new.html.erb.tt -->

<div class="container mx-auto my-8 px-4">
  <div class="max-w-xl mx-auto">
    <h1 class="text-2xl font-bold mb-6">New <%= singular_table_name.titleize %></h1>

    <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>

    <%%= link_to 'Back', <%= index_helper %>_path, class: "link" %>
  </div>
</div>

```

### The show view template

```erb
<!-- lib/templates/erb/scaffold/show.html.erb.tt -->

<div class="container mx-auto my-8 px-4">
  <% attributes.reject(&:password_digest?).each do |attribute| -%>
  <p class="text-lg font-semibold"><%= attribute.human_name %>:</p>
  <p class="leading-normal"><%%= @<%= singular_table_name %>.<%= attribute.name %> %></p>

  <% end -%>
  <div class="flex items-center justify-start mt-6">
    <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: "btn btn-default mr-4" %>
    <%%= link_to 'Back', <%= index_helper %>_path, class: "btn btn-default" %>
  </div>
</div>

```

### The \_form view template

```erb
<!-- lib/templates/erb/scaffold/_form.html.erb.tt -->

<%%= form_with(model: <%= model_resource_name %>) do |form| %>
  <%%= render "error_messages", resource: form.object %>

<% attributes.each do |attribute| -%>
  <div class="mb-6">
<% if attribute.password_digest? -%>
    <%%= form.label :password, class: "label" %>
    <%%= form.password_field :password, class: "input" %>
  </div>

  <div class="mb-6">
    <%%= form.label :password_confirmation, class: "label" %>
    <%%= form.password_field :password_confirmation, class: "input" %>
<% else %>
    <%%= form.label :<%= attribute.column_name %>, class: "label" %>
    <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, class: "input" %>
<% end %>
  </div>

<% end -%>
  <div class="mb-6 flex justify-between items-center">
    <%%= form.button class: "btn btn-default" %>

    <%% if form.object.persisted? %>
      <%%= link_to 'Delete', form.object, class: "btn btn-default", method: :delete, data: { remote: true, confirm: "Are you sure?" } %>
    <%% end %>
  </div>
<%% end %>

```

### Let the magic begin

With these sets of templates in place, you can now create new scaffolds that will harness them instead of the defaults that come with Rails. What’s great here is that you can go as crazy or simple as you want with the template depending on your needs. In my own case, I might extend my rails application template Kickstart to use these for future screencasts/tutorials. It saves a ton of time and brain power which is the point of the framework.

I hope you found this technique useful. I find it really empowering to be able to simply add some templates and let the app/framework take it from there. There was little to no configuration which is a big selling point for Ruby on Rails and why I continue to love working with this framework every day.

### Shameless plug!

[![](https://i1.wp.com/web-crunch.com/wp-content/uploads/2019/01/YouTube-Promo3.jpg?resize=3840%2C2160&ssl=1)](http://hellorails.io)

I have a new course called [Hello Rails](https://hellorails.io). Hello Rails is a modern course designed to help you start using and understanding Ruby on Rails fast. If you’re a novice when it comes to Ruby or Ruby on Rails I invite you to check out the site. The course will be much like these builds but a super more in-depth version with more realistic goals and deliverables. [Sign up to get notified today](https://hellorails.io/)!

Follow [@hello\_rails](https://twitter.com/hello_rails) and [myself @justalever](https://twitter.com/justalever) on Twitter.

The post [How to Create Custom Scaffold Templates in Ruby on Rails](https://web-crunch.com/how-to-create-custom-scaffold-templates-in-ruby-on-rails/) appeared first on [Web-Crunch](https://web-crunch.com).