Rails Scaffold Generator

Noah Eakin
3 min readDec 1, 2020

Rails was designed with a focus on making the work of a developer easier. One of the ways it accomplishes this is by providing tools to automate core, commonly-used functionality. Generators encapsulate this idea, building out models, migrations, routes, and other assets by taking some parameters and quickly implementing our boilerplate code for us. This process is standardized which limits the potential for human error while also speeding up one of the more tedious aspects of developing a new project.

This can occasionally be a slippery slope as the convenience of these generators can tempt us to generate needless files, potentially confounding future collaborators with this unused filler. Generally, a developer should use the most lightweight generator that still meets her needs.

In this post, however, I want to focus on the heaviest of hitters: scaffold generators.

Getting Started

Typing rails generate or rails g while in our project directory will give us all of our Rails generators:

Rails:
application_record
channel
controller
generator
integration_test
job
mailbox
mailer
migration
model
resource
scaffold
scaffold_controller
system_test
task

Amongst the lighter-weight migration, model, and controller generators we can see our scaffold generator. Now, let’s take a closer look and see why this is such a powerful tool.

Rails Magic

In my coding bootcamp, we were allowed to use all of the generators except for scaffold during our Rails module. The reason for this is that scaffold generators take so much of the work out of the developer’s hands — a great thing for a more experienced developer but not the best idea for someone learning the Rails framework for the first time.

The basic format of the scaffold generator command is rails g scaffold <name of model> <model attributes>. So, what happens when we run rails g scaffold Puppy name age:integer disposition? Take a look:

$ rails generate scaffold Puppy name:string age:integer      disposition:stringinvoke  active_record
create db/migrate/20190416145729_create_puppies.rb
create app/models/puppy.rb
invoke test_unit
create test/models/puppy_test.rb
create test/fixtures/puppies.yml
invoke resource_route
route resources :puppies
invoke scaffold_controller
create app/controllers/puppies_controller.rb
invoke erb
create app/views/puppies
create app/views/puppies/index.html.erb
create app/views/puppies/edit.html.erb
create app/views/puppies/show.html.erb
create app/views/puppies/new.html.erb
create app/views/puppies/_form.html.erb
invoke test_unit
create test/controllers/puppies_controller_test.rb
create test/system/puppies_test.rb
invoke helper
create app/helpers/puppies_helper.rb
invoke test_unit
invoke jbuilder
create app/views/puppies/index.json.jbuilder
create app/views/puppies/show.json.jbuilder
create app/views/puppies/_puppy.json.jbuilder
invoke assets
invoke scss
create app/assets/stylesheets/puppies.scss
invoke scss
create app/assets/stylesheets/scaffolds.scss

That is a TON of stuff. Here’s a basic breakdown of what’s happening:

  • Created migration for a new database table with the attributes we supplied
  • Created accompanying model file that inherits from ApplicationRecord
  • Created controller file that inherits from ApplicationController, complete with basic CRUD methods as well as the private methods #set_puppy and #puppy_params
  • Created view directory which holds newly generated index, edit, show, new, and form template files
  • Created a scss file for controller styling
  • Created a route within the routes.rb file with full resources
  • Uses Jbuilder to help write JSON in views
  • Added basic tests for models and controllers

The main differences between scaffold generator and resource generator come in the form of the view template files which are absent in the latter, as well as some magic in the controller. If you know you will have a resource that utilizes full CRUD, scaffold generator may be the way to go since it takes care of that chunk of boilerplate for you:

class PuppiesController < ApplicationController
before_action :set_puppy, only: [:show, :update, :destroy]
def index
@puppies = Puppy.all
render json: @puppies
end
def show
render json: @puppy
end
def create
@puppy = Puppy.new(puppy_params)
if @puppy.save
render json: @puppy, status: :created, location: @puppy
else
render json: @puppy.errors, status: :unprocessable_entity
end
end
def update
if @puppy.update(puppy_params)
render json: @puppy
else
render json: @puppy.errors, status: :unprocessable_entity
end
end
def destroy
@puppy.destroy
end
private

def set_puppy
@puppy = Puppy.find(params[:id])
end
def puppy_params
params.require(:puppy).permit(:name, :age, :disposition)
end
end

Again, if we have a controller that needs CRUD this saves us a bunch of time and limits room for errors that can arise when manually inputting this much code.

One final note: if you generate your Rails app with the API flag --api because you have a separate front end, you do not have to worry about Rails generating those View templates. It is smart enough to know that they are not needed for your project and will skip that step.

After previously fleshing this functionality out by hand, this sort of utility can almost seem like cheating. But you’ve earned your wings so go on and treat yourself with some scaffolding!

--

--