Build great views fast - Custom view scaffolding in rails with bootstrap 4
Tags: rails, bootstrap
Published: 2020-01-29 06:26:20


Scaffolding views in rails can save a lot of time, however the default scaffolded views are too plain to be useful. By using custom scaffolding with bootstrap 4, it's easy to quickly create views that look good and only 5 additional files are needed!!!

From this
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3kuz2245p5n124dfbuxj.png)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/tn5czbbo7kh5zjegg9lw.png)


To this 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/9q3o4fygu92fdp2yvfmt.png)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/wj07jbeunhv2g0y4y372.png)




The existing scaffolding templates are under the railties directory, located in /lib/rails/generators/erb/scaffold/templates

The following command shows where railties is located. 

```
bundle show railties
```

### Edit Config

in config/application.rb add

```ruby
 config.generators do |g|
      g.orm             :active_record
      g.template_engine :erb
      g.test_framework  :test_unit, fixture: true
    end
```


### Create template files
Then in the project lib directory create the following folders

template/erb/scaffold

The custom scaffolding templates are placed in this folder, and override the default scaffolding templates.

Create the following files
lib/templates/erb/scaffold/_form.html.erb.tt
lib/templates/erb/scaffold/edit.html.erb.tt
lib/templates/erb/scaffold/index.html.erb.tt
lib/templates/erb/scaffold/new.html.erb.tt
lib/templates/erb/scaffold/show.html.erb.tt



####_form.html.erb.tt
```erb
<%%= form_with(model: <%= singular_table_name %>, local: true) do |form| %>
  <%% if <%= singular_table_name %>.errors.any? %>
    <div id="error_explanation" class="alert alert-danger" role="alert">
      <h5><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h5>
      <ul>
      <%% <%= singular_table_name %>.errors.full_messages.each do |message| %>
        <li><%%= message %></li>
      <%% end %>
      </ul>
    </div>
  <%% end %>
  <% attributes.each do |attribute| -%>
    <% if attribute.password_digest? -%>
      <div class="form-group">
        <%%= form.label :password %>
        <%%= form.password_field :password, id: :<%= field_id(:password) %>,class:"form-control"%>
      </div>
      <div class="form-group">
        <%%= form.label :password_confirmation %>
        <%%= form.password_field :password_confirmation, id: :<%= field_id(:password_confirmation) %> ,class:"form-control" %>
      </div>
    <% elsif attribute.type == :boolean -%>
      <div class="form-group form-check">
      <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, id: :<%= field_id(attribute.column_name) %> ,class:"form-check-input"%>
      <%%= form.label :<%= attribute.column_name %>, class:"form-check-label"%>
      </div>
    <% else -%>
      <div class="form-group">
        <%%= form.label :<%= attribute.column_name %> %>
        <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, id: :<%= field_id(attribute.column_name) %> ,class:"form-control"%>
      </div>
    <% end -%>
  <% end -%>
  <div class="actions">
    <%%= form.submit "Save", class:"btn btn-success min-width-btn" %>
  </div>
<%% end %>
```



####edit.html.erb.tt

```erb

<div class="container-fluid">
    <h1>Editing <%= singular_table_name.titleize %></h1>
    <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
    <br>
    <%%= link_to 'Show', @<%= singular_table_name %>, class:"btn btn-light min-width-btn" %>
    <%%= link_to 'Back', <%= index_helper %>_path, class:"btn btn-light min-width-btn" %>
</div>
```



####index.html.erb.tt

```erb

<div class="container-fluid">
  <h1><%= plural_table_name.titleize %></h1>
  <table class="table">
    <thead>
      <tr>
        <% attributes.reject(&:password_digest?).each do |attribute| -%>
          <th><%= attribute.human_name %></th>
        <% end -%>
        <th></th>
      </tr>
    </thead>
    <tbody>
      <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
        <tr>
          <% attributes.reject(&:password_digest?).each do |attribute| -%>
            <td>
              <%%= <%= singular_table_name %>.<%= attribute.name %> %>
            </td>      
          <% end -%>
          <td>
          <%%= link_to 'Show', <%= singular_table_name %>, class:"btn btn-light min-width-btn" %>
          <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>),class:"btn btn-primary min-width-btn"  %>     
          <%%= link_to 'Delete', <%= singular_table_name %>, method: :delete, data: { confirm: 'Are you sure?' }, class:"btn btn-danger min-width-btn"%>
          </td>
        </tr>
      <%% end %>
    </tbody>
  </table>
  <br>
  <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_table_name %>_path,class:"btn btn-success min-width-btn" %>
</div>
```



####new.html.erb.tt
```erb
<div class="container-fluid">
    <h1>New <%= singular_table_name.titleize %></h1>
    <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
    <br>
    <%%= link_to 'Back', <%= index_helper %>_path, class:"btn btn-light min-width-btn" %>
</div>
```



####show.html.erb.tt
```erb

<div class="container-fluid">
  <h1><%= singular_table_name.titleize %> Details</h1>
  <%%= form_with(model: @<%= singular_table_name %>, local: true) do |form| %>
    <% attributes.each do |attribute| -%>
      <% if attribute.type == :boolean -%>
        <div class="form-group form-check">
          <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, id: :<%= field_id(attribute.column_name) %> ,class:"form-check-input", disabled:true%>
          <%%= form.label :<%= attribute.column_name %>, class:"form-check-label"%>
        </div>
      <% else -%>
        <div class="form-group">
          <%%= form.label :<%= attribute.column_name %> %>
          <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, id: :<%= field_id(attribute.column_name) %> ,class:"form-control", readonly:true%>
        </div>
      <% end -%>
    <% end -%>
  <%% end %>
  <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>),class:"btn btn-primary min-width-btn" %> 
  <%%= link_to 'Back', <%= index_helper %>_path,class:"btn btn-light min-width-btn" %>
</div>

```


### Add Bootstrap 4

add the bootstrap 4 ruby gem to the gemfile and follow the configuration steps in [https://github.com/twbs/bootstrap-rubygem](https://github.com/twbs/bootstrap-rubygem)

```
gem 'bootstrap', '~> 4.4.1'
```


### Add additional CSS
in app/assets/stylesheets/application.scss add the following

```css
 .min-width-btn {
    min-width:100px;
    margin:1px;
  }
```

### Run the scaffolder

Generate new views for the restaurant model overriding the original ones.

```
rails g erb:scaffold Restaurant name description phone time_zone currency active:boolean
```

### All done
Enjoy the much improved views.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ic41py3o63ezyu338e15.png)