SlideShare una empresa de Scribd logo
1 de 32
Descargar para leer sin conexión
Simplify 
Your Rails Controllers 
With a Vengeance
Brian Auton 
brianauton@gmail.com 
twitter.com/brianauton 
github.com/brianauton
I know what's wrong 
with your Rails app...
The controllers 
(they're too complex)
1. Less responsibilities 
2. Shorter methods 
3. Less duplication
1. Less responsibilities 
2. Shorter methods 
3. Less duplication 
Controllers are just code.
1. Less responsibilities 
User's Intent <=> Business Logic
1. Less responsibilities 
User's Intent <=> Business Logic 
How? REST
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
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
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
routes.rb 
resources :orders 
resources :payment_attempts, only: :create 
payment_attempts_controller.rb 
def create 
attempt = PaymentAttempt.create payment_attempt_params 
PaymentGateway.process attempt.order 
flash[:notice] = “Payment successful” 
attempt.update_attribute :status, :complete 
rescue PaymentGateway::Error => e 
attempt.update_attribute :error, e.message 
redirect_to attempt.order, alert: “Error: #{e.message}” 
end
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
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
2. Shorter methods
2. Shorter methods 
How? Delegate to models
payment_attempts_controller.rb 
def create 
attempt = PaymentAttempt.create payment_attempt_params 
PaymentGateway.process attempt.order 
flash[:notice] = “Payment successful” 
attempt.update_attribute :status, :complete 
rescue PaymentGateway::Error => e 
attempt.update_attribute :error, e.message 
redirect_to attempt.order, alert: “Error: #{e.message}” 
end
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
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
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
users_controller.rb 
def update 
@user = User.find params[:id] 
@user.update_attributes user_params 
... 
end 
def user_params 
params.require(:user).permit :name, :email, { 
address_attributes: [:city, :state, :zip] 
} 
end 
user.rb 
has_one :address 
accepts_nested_attributes_for :address
3. Reduce Duplication
3. Reduce Duplication 
How? It's just code.
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
widgets_controller.rb 
before_action :build_widget, only: [:new] 
before_action :find_widget, only: [:show, :update] 
private 
def build_widget 
@widget = Widget.new 
end 
def find_widget 
@widget = Widget.find params[:id] 
end
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
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
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
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
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
Recap: 
1. Less responsibilities (REST) 
2. Shorter methods (Models) 
3. Less duplication
Go try it out! 
brianauton@gmail.com 
twitter.com/brianauton 
github.com/brianauton

Más contenido relacionado

La actualidad más candente

Cucumber: How I Slice It
Cucumber: How I Slice ItCucumber: How I Slice It
Cucumber: How I Slice Itlinoj
 
RoR 101: Session 3
RoR 101: Session 3RoR 101: Session 3
RoR 101: Session 3Rory Gianni
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - IntroductionVagmi Mudumbai
 
Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009bturnbull
 
Simple Contact Us Plugin Development
Simple Contact Us Plugin DevelopmentSimple Contact Us Plugin Development
Simple Contact Us Plugin Developmentwpnepal
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & BackboneAshan Fernando
 
What's new in Rails 5 - API Mode & Action Cable overview
What's new in Rails 5 - API Mode & Action Cable overviewWhat's new in Rails 5 - API Mode & Action Cable overview
What's new in Rails 5 - API Mode & Action Cable overviewMaxim Veksler
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_snetwix
 
Active Admin: Create Your Admin Interface the Easy Way
Active Admin: Create Your Admin Interface the Easy WayActive Admin: Create Your Admin Interface the Easy Way
Active Admin: Create Your Admin Interface the Easy WaySmartLogic
 
Zend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarZend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarRalph Schindler
 
Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Sumy PHP User Grpoup
 
Rails engines in large apps
Rails engines in large appsRails engines in large apps
Rails engines in large appsEnrico Teotti
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJSRajthilakMCA
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Vikas Chauhan
 

La actualidad más candente (20)

Cucumber: How I Slice It
Cucumber: How I Slice ItCucumber: How I Slice It
Cucumber: How I Slice It
 
RoR 101: Session 3
RoR 101: Session 3RoR 101: Session 3
RoR 101: Session 3
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
 
Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009Rails 2.3 and Rack - NHRuby Feb 2009
Rails 2.3 and Rack - NHRuby Feb 2009
 
Simple Contact Us Plugin Development
Simple Contact Us Plugin DevelopmentSimple Contact Us Plugin Development
Simple Contact Us Plugin Development
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & Backbone
 
Zend framework
Zend frameworkZend framework
Zend framework
 
What's new in Rails 5 - API Mode & Action Cable overview
What's new in Rails 5 - API Mode & Action Cable overviewWhat's new in Rails 5 - API Mode & Action Cable overview
What's new in Rails 5 - API Mode & Action Cable overview
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
13.exemplu closure controller
13.exemplu closure controller13.exemplu closure controller
13.exemplu closure controller
 
Simple restfull app_s
Simple restfull app_sSimple restfull app_s
Simple restfull app_s
 
Active Admin: Create Your Admin Interface the Easy Way
Active Admin: Create Your Admin Interface the Easy WayActive Admin: Create Your Admin Interface the Easy Way
Active Admin: Create Your Admin Interface the Easy Way
 
Zend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarZend Framework 1.8 Features Webinar
Zend Framework 1.8 Features Webinar
 
Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2Service approach for development Rest API in Symfony2
Service approach for development Rest API in Symfony2
 
Rails engines in large apps
Rails engines in large appsRails engines in large apps
Rails engines in large apps
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
 
Javascript laravel's friend
Javascript laravel's friendJavascript laravel's friend
Javascript laravel's friend
 
Redmine Betabeers SVQ
Redmine Betabeers SVQRedmine Betabeers SVQ
Redmine Betabeers SVQ
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJS
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2
 

Similar a Simplify Your Rails Controllers With a Vengeance

More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weiboshaokun
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Ruby on Rails : RESTful 和 Ajax
Ruby on Rails : RESTful 和 AjaxRuby on Rails : RESTful 和 Ajax
Ruby on Rails : RESTful 和 AjaxWen-Tien Chang
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30fiyuer
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails Mohit Jain
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
Advanced RESTful Rails
Advanced RESTful RailsAdvanced RESTful Rails
Advanced RESTful RailsViget Labs
 
WebcampZG - Rails 4
WebcampZG - Rails 4WebcampZG - Rails 4
WebcampZG - Rails 4shnikola
 
Using the Features API
Using the Features APIUsing the Features API
Using the Features APIcgmonroe
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Resource and view
Resource and viewResource and view
Resource and viewPapp Laszlo
 
Rails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowRails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowChris Oliver
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Coupa Software
 
Rails best practices_slides
Rails best practices_slidesRails best practices_slides
Rails best practices_slidesCao Van An
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Codescidept
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonManageIQ
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatternsChul Ju Hong
 
Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)lazyatom
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-publicChul Ju Hong
 

Similar a Simplify Your Rails Controllers With a Vengeance (20)

More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Ruby on Rails : RESTful 和 Ajax
Ruby on Rails : RESTful 和 AjaxRuby on Rails : RESTful 和 Ajax
Ruby on Rails : RESTful 和 Ajax
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
Advanced RESTful Rails
Advanced RESTful RailsAdvanced RESTful Rails
Advanced RESTful Rails
 
The Rails Way
The Rails WayThe Rails Way
The Rails Way
 
WebcampZG - Rails 4
WebcampZG - Rails 4WebcampZG - Rails 4
WebcampZG - Rails 4
 
Using the Features API
Using the Features APIUsing the Features API
Using the Features API
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Resource and view
Resource and viewResource and view
Resource and view
 
Rails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not KnowRails World 2023: Powerful Rails Features You Might Not Know
Rails World 2023: Powerful Rails Features You Might Not Know
 
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
Staying railsy - while scaling complexity or Ruby on Rails in Enterprise Soft...
 
Rails best practices_slides
Rails best practices_slidesRails best practices_slides
Rails best practices_slides
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Design Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron PattersonDesign Summit - Rails 4 Migration - Aaron Patterson
Design Summit - Rails 4 Migration - Aaron Patterson
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatterns
 
Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-public
 

Último

So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 

Último (20)

So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 

Simplify Your Rails Controllers With a Vengeance

  • 1. Simplify Your Rails Controllers With a Vengeance
  • 2. Brian Auton brianauton@gmail.com twitter.com/brianauton github.com/brianauton
  • 3. I know what's wrong with your Rails app...
  • 5. 1. Less responsibilities 2. Shorter methods 3. Less duplication
  • 6. 1. Less responsibilities 2. Shorter methods 3. Less duplication Controllers are just code.
  • 7. 1. Less responsibilities User's Intent <=> Business Logic
  • 8. 1. Less responsibilities User's Intent <=> Business Logic How? REST
  • 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
  • 12. routes.rb resources :orders resources :payment_attempts, only: :create payment_attempts_controller.rb def create attempt = PaymentAttempt.create payment_attempt_params PaymentGateway.process attempt.order flash[:notice] = “Payment successful” attempt.update_attribute :status, :complete rescue PaymentGateway::Error => e attempt.update_attribute :error, e.message redirect_to attempt.order, alert: “Error: #{e.message}” 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
  • 16. 2. Shorter methods How? Delegate to models
  • 17. payment_attempts_controller.rb def create attempt = PaymentAttempt.create payment_attempt_params PaymentGateway.process attempt.order flash[:notice] = “Payment successful” attempt.update_attribute :status, :complete rescue PaymentGateway::Error => e attempt.update_attribute :error, e.message redirect_to attempt.order, alert: “Error: #{e.message}” 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
  • 21. users_controller.rb def update @user = User.find params[:id] @user.update_attributes user_params ... end def user_params params.require(:user).permit :name, :email, { address_attributes: [:city, :state, :zip] } end user.rb has_one :address accepts_nested_attributes_for :address
  • 23. 3. Reduce Duplication How? It's just code.
  • 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
  • 25. widgets_controller.rb before_action :build_widget, only: [:new] before_action :find_widget, only: [:show, :update] private def build_widget @widget = Widget.new end def find_widget @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