9. routes.rb
resources :clients do
get :download_pdf, on: :member
end
clients_controller.rb
def download_pdf
client = Client.find params[:id]
send_data client.to_pdf, type: :pdf
end
def show
@client = Client.find params[:id]
end
10. routes.rb
resources :clients
clients_controller.rb
def show
@client = Client.find params[:id]
respond_to do |format|
format.html {}
format.pdf do
send_data @client.to_pdf, type: :pdf
end
end
end
11. routes.rb
resources :orders do
post :submit, on: :member
end
orders_controller.rb
def submit
order = Order.find params[:id]
PaymentGateway.process order
flash[:notice] = “Payment successful”
order.update_attribute :status, :complete
rescue PaymentGateway::Error => e
order.update_attribute :status, :failed
redirect_to order, alert: “Error: #{e}”
end
13. routes.rb
resources :regions do
put :sort, on: :collection
end
regions_controller.rb
def sort
params[:region].each do |id, position|
Region.find(id).update_attribute :position, position
end
end
14. routes.rb
resources :regions
resources :region_collections, only: :update
region_collections_controller.rb
def update
region_collection_params.each do |attributes|
Region.find(attributes[:id)].update_attributes attributes
end
end
private
def region_collection_params
params.require(:region_collection).permit [:id, :position]
end
18. payment_attempt.rb
class PaymentAttempt < ActiveRecord::Base
before_save do
PaymentGateway.process order
rescue PaymentGateway::Error => e
update_attribute :error, e.message
end
def successful?
error.present?
end
end
19. payment_attempts_controller.rb
def create
@attempt = PaymentAttempt.create payment_attempt_params
if @attempt.successful?
flash[:notice] = “Payment successful.”
else
flash[:alert] = “Error: #{@attempt.error}”
redirect_to @attempt.order
end
end
20. users_controller.rb
def update
@user = User.find params[:id]
@user.update_attributes user_params
@user.address.update_attributes address_params
...
end
def user_params
params.require(:user).permit :name, :email
end
def address_params
params.require(:address).permit :city, :state, :zip
end
24. widgets_controller.rb
def new
@widget = Widget.new
end
def show
@widget = Widget.find params[:id]
end
def update
@widget = Widget.find params[:id]
...
end
26. application_controller.rb
protected
def build_member
set_member_instance_variable collection.new
end
def find_member
set_member_instance_variable collection.find(params[:id])
end
def set_member_instance_variable(value)
variable_name = “@#{controller_name.singularize}”
instance_variable_set variable_name, (@member = value)
end
def collection
controller_name.classify.constantize
end
27. assets_controller.rb
def update
if @asset.update_attributes asset_params
redirect_to @asset, notice: “Asset updated”
else
flash[:alert] = @asset.errors.full_messages.join(', ')
render :edit
end
end
surveys_controller.rb
def update
if @survey.update_attributes survey_params
redirect_to @survey, notice: “Survey updated”
else
flash[:alert] = @survey.errors.full_messages.join(', ')
render :edit
end
end
28. assets_controller.rb
def update
@asset.update_attributes asset_params
respond_to_update @asset
end
surveys_controller.rb
def update
@survey.update_attributes survey_params
respond_to_update @survey
end
application_controller.rb
def respond_to_update(model)
if model.valid?
type = model.class.name.humanize
redirect_to model, notice: “#{type} updated”
else
flash[:alert] = model.errors.full_messages.join(', ')
render :edit
end
end
29. shared_rest_actions.rb
module SharedRestActions
def self.included(base)
base.before_action :build_member, only: [:new, :create]
base.before_action :find_collection, only: :index
base.before_action :find_member, except: [:index, :new, :create]
end
def index
end
def update
member_params = send “#{controller_name.singularize}_params”
@member.update_attribute member_params
respond_to_update @member
end
...
end
30. assets_controller.rb
class AssetsController < ApplicationController
include SharedRestActions
before_action :paginate, only: :index
before_action :sort_by_date, only: :index
end
surveys_controller.rb
class SurveysController < ApplicationController
include SharedRestActions
before_action :build_member, only: :index
end
31. Recap:
1. Less responsibilities (REST)
2. Shorter methods (Models)
3. Less duplication
32. Go try it out!
brianauton@gmail.com
twitter.com/brianauton
github.com/brianauton