Rails Generators – Model vs. Resource vs. Scaffold

matt readout
4 min readJul 14, 2019

--

Photo by Antoine Beauvillain on Unsplash

Part of the beauty of Rails is just how much you (and by you of course I mean Rails, you lazy bum) can do with a handful of keystrokes at the command line. Anyone who’s ever entered rails new <whatever> knows that feeling of excitement watching the framework fly into action, creating everything you need to start building your app. It’s kind of like the feeling of being on a roller coaster as the car flies over the first big hill on those.. tracks? Metal wheel guides? Should really be a better name for those. ¯\_(ツ)_/¯

Rails Generate

The rails generate command, or rails g when you want to impress your shortcut-obsessed friends, unlocks some of the real time-saving power of Rails. Using templates to generate boilerplate code, you don’t have spend time writing the same thing every time you create a new app — code that you’ll always write just to get things running. By running rails generate with no arguments, you can see all of the generators that come baked-in:

Rails:
application_record
channel
controller
generator
integration_test
job
mailer
migration
model
resource
scaffold
scaffold_controller
system_test
task
ActiveRecord:
active_record:application_record
active_record:migration
active_record:model
Serializer:
serializer
TestUnit:
test_unit:controller
test_unit:generator
test_unit:helper
test_unit:integration
test_unit:job
test_unit:mailer
test_unit:model
test_unit:plugin
test_unit:scaffold
test_unit:system

That’s right, you can rails generate a generator! Although as exciting as that sounds, let’s look at the difference between generating individual models, resources, or an entire scaffold.

Model

The simplest and most lightweight of the three is the model generator. Let’s say we’re setting up our app’s backend and we want to generate a User model. Running rails generate User name username email will create the following:

# a migration in db/migrate/20190714193807_create_users.rbclass CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.string :username
t.string :email
t.timestamps
end
end
end
# the User model in app/models/user.rbclass User < ApplicationRecord
end
# as well as a couple test stubs in test/

Using the model generator does the least amount of work for you, but also creates the fewest number of files, etc. giving you more control over what is actually written.

Resource

Using the resource generator gives you even more to start with — running rails generate resource User name username email magically (not actually magically) creates:

# a migration in db/migrate/20190714193807_create_users.rbclass CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.string :username
t.string :email
t.timestamps
end
end
end
# the User model in app/models/user.rbclass User < ApplicationRecord
end
# a User controller in app/controllers/users_controller.rbclass UsersController < ApplicationController
end
# opens up all of the routes in config/routes.rbRails.application.routes.draw do
resources :users
end
# even more tests

As you can see, this saves you the time of creating more files, but still leaves most of the code writing up to you.

Scaffold

Now, when you really want to see the power of Rails generators (and indulge in a little existential crisis about who’s actually writing the code here, the developer or Rails?), you can generate a scaffold. Again, for our User model — rails generate scaffold User name username email gives us:

# a migration in db/migrate/20190714193807_create_users.rbclass CreateUsers < ActiveRecord::Migration[5.2]
def change
create_table :users do |t|
t.string :name
t.string :username
t.string :email
t.timestamps
end
end
end
# the User model in app/models/user.rbclass User < ApplicationRecord
end
# opens up all of the routes in config/routes.rbRails.application.routes.draw do
resources :users
end
# tests tests tests

But here’s where some of the real time-saving power comes in! It also generates a controller in app/controllers/users_controller.rb but with public methods for the basic CRUD functions, as well as two private methods, #set_user and #user_params:

class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
# GET /users
def index
@users = User.all
render json: @users
end
# GET /users/1
def show
render json: @user
end
# POST /users
def create
@user = User.new(user_params)
if @user.save
render json: @user, status: :created, location: @user
else
render json: @user.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /users/1
def update
if @user.update(user_params)
render json: @user
else
render json: @user.errors, status: :unprocessable_entity
end
end
# DELETE /users/1
def destroy
@user.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:name, :username, :email)
end
end

If you’ve worked on a few Rails projects, you know how many times you end up writing exactly the same code when defining models and setting up basic CRUD functionality. Making smart use of these generators can save you plenty of time!

--

--