Resourceful Girl

William Vetter
4 min readOct 19, 2020

For a while, we’ve been building out Rails applications “the ol’ fashioned” way — that is to say, creating our migrations by hand, with something like:

rails g migration CreateDogs name:string --no-test-framework

And then perhaps adding to that migration with:

rails g migration AddOwnerToDogs owner:belongs_to --no-test-framework

Rails is smart enough to know that because of the “Add” naming convention, it will assume that you’re adding a column to the table.

We’ve also been creating the model and controller by hand:

#..app/models/dog.rb
class Dog << ActiveRecord::Base
end
#..app/controllers/dogs_controller.rbclass DogsController < ApplicationController def index
@dogs = Dog.all
render 'index'
end
def show
@dog = Dog.find(params[:id])
render 'show'
end
def new
@dog = Dog.new
render 'new'
end
end

On top of this, we’ve had to create a dogs folder in view corresponding to each model (e.g. Dogs, Owners, etc.), while also defining the routes themselves in “config/routes.rb”:

#../config/routes.rbRails.application.routes.draw do     get ‘/dogs’, to: ‘dogs#index’     get ‘/dogs/:id’, to: ‘dogs#show’     get '/dogs/new', to: 'dogs#new'end

This is laborious. As programmers, if it’s one thing to be sure of, it’s that someone, somewhere, has probably had the same qualms as you, and devised a way to make their job easier. This makes our job easier (if they shared!).

rails g resource Dog name:string owner:belongs_to --no-test-framework

This single line will do everything for us (plus a little extra!). We just need to understand exactly what this does, and we’ll be set to start writing code in seconds!

This will do the following, based on the name Dog:

  1. Create a migration file:
#../db/migrate/20160113001427_create_dogs.rbclass CreatePosts < ActiveRecord::Migration  
def change
create_table :dogs do |d|
t.string :name
t.belongs_to :owner
t.timestamps null: false
end
end
end

2. Create the model & controller:

#../app/controllers/dogs_controller.rb
class DogsController < ApplicationController
end

Notice that rails g resource will also add any associations if you defined them in the same line (e.g. owner:belongs_to as shown above):

#../app/models/dog.rb
class Dog < ActiveRecord::Base
belongs_to :owner
end

3. Create the dogs folder within the views folder, and defines the route:

#../config/routes.rbRails.application.routes.draw do     resources :dogsend

There isn’t much difference in the code generated ‘by hand’, and the code generated with rails g resource. But that’s the beauty of it — given a single name, i.e. Dog, rails knows how to create the base foundation for the files you want to make anyways!

The main difference between what we’ve conventionally done, is in the resources :dogs.

This bit says that we’re probably also trying to create the 7 CRUD action/paths for /dogs.

Since we already have our controller defined as above, we technically don’t need to define any sort of controller actions, like we did previously:

#..app/controllers/dogs_controller.rbclass DogsController < ApplicationController     def index
@dogs = Dog.all
render 'index'
end
def show
@dog = Dog.find(params[:id])
render 'show'
end
def new
@dog = Dog.new
render 'new'
end
end

The line we have, resources :dogs, assumes that we already want the controller actions “index”, “show”, “new”, “create”, “edit”, “update”, and “delete”.

We technically don’t need to even define them in the controller.

If you deleted the def index action from DogsController, but still at least had a view that read:

#..app/views/dogs/index.html.erb<h1>Hello!</h1>

And navigated to http://localhost:3000/dogs, you’d be welcomed with a big Hello!

Why is this? Because Rails just knows. It does know you.

… But also, because saying resources :dogs will auto-magically define those 7 methods within the controller action, THUS allowing the 7 paths to be used:

#index#   GET /dogs
#show# GET /dogs/:id
#new# GET /dogs/new
#create# POST /dogs
#edit# GET /dogs/:id/edit
#update# PATCH /dogs/:id
#detroy# DESTROY /dogs/:id

The only reason we define them within controller ourselves, is because we’re also usually passing values, such as the need to display a particular Dog object by saying:

def show
@dog = Dog.find(params[:id])
end

Our view also needs that object — we’re not just trying to say “Hello!” to someone.

If we were trying to make some more complex assocations, we could do something like :

rails g resource Dog name owner:belongs_to toys:has_many --no-test-frameworkrails g resource Owner name dogs:has_many --no-test-frameworkrails g resource Toy name dog:belongs_to --no-test-framework

In addition to everything we’ve talked about, within our models, the associations will also be defined:

class Dog
belongs_to :owner
has_many :toys
end

And voila! You’re ready to start coding within your pre-designated files and folders!

Using this generator will create a little extra fluff for us, but we needn’t worry about that for now. Just as long as you use the appropriate generators and understand their capabilities, you’ll be creating projects even faster than before.

Take care.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

William Vetter
William Vetter

Written by William Vetter

0 Followers

Full Stack Developer based in Ann Arbor, Michigan. Javascript, Ruby, ReactJS, React Native, and more! 2008–2013 Super Smash Bros professionále

No responses yet

Write a response