Fellow Rails Developers, the state of the art has moved on, and you should no longer be using the controllers generated by Rails’ scaffold command (or ‘rails g resource foo’).
These controllers are all the same. Repetition like that can and should be eliminated.
Instead, you should use something like Inherited Resources.
Here’s what a controller generated by Rails looks like:
class UsersController < ApplicationController
# GET /users
# GET /users.xml
def index
@users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @users }
end
end
# GET /users/1
# GET /users/1.xml
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/new
# GET /users/new.xml
def new
@user = User.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @user }
end
end
# GET /users/1/edit
def edit
@user = User.find(params[:id])
end
# POST /users
# POST /users.xml
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
# PUT /users/1
# PUT /users/1.xml
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
format.html { redirect_to(@user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
@user = User.find(params[:id])
@user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
end
Here’s that SAME controller using Inherited Resources:
class UsersController < InheritedResources::Base
end
That’s right, just by inheriting from InheritedResources::Base you all the standard REST actions for free.
If you need to, you can override any of the default actions:
class UsersController < InheritedResources::Base
def new
# do different stuff for new
end
end
It even has a nice DSL for customizations you’re likely to need. Here’s how to change just the redirect for the destroy action:
class UsersController < InheritedResources::Base
def destroy
destroy!{ root_url }
end
end
The best thing is, once you’ve got that duplicated code out of there, you don’t need to test it! Inherited Resources already has its own tests for the standard actions, so you only need test the things you explicitly change.
A few months ago, I refactored an app to use Inherited Resources instead of the generated controllers. And by ‘refactored’, I mean ‘deleted pages and pages of controller and test code’. I ‘git rm’d almost all our functional tests and damn that felt good.
You gotta get in on this! The README is solid, so you should have little trouble getting started.