SlideShare a Scribd company logo
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

More Related Content

What's hot

Cucumber: How I Slice It
Cucumber: How I Slice ItCucumber: How I Slice It
Cucumber: How I Slice It
linoj
 
RoR 101: Session 3
RoR 101: Session 3RoR 101: Session 3
RoR 101: Session 3
Rory Gianni
 
Ruby on Rails - Introduction
Ruby on Rails - IntroductionRuby on Rails - Introduction
Ruby on Rails - Introduction
Vagmi 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 2009
bturnbull
 
Simple Contact Us Plugin Development
Simple Contact Us Plugin DevelopmentSimple Contact Us Plugin Development
Simple Contact Us Plugin Development
wpnepal
 
SPA using Rails & Backbone
SPA using Rails & BackboneSPA using Rails & Backbone
SPA using Rails & Backbone
Ashan Fernando
 
Zend framework
Zend frameworkZend framework
Zend framework
Prem Shankar
 
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
Maxim Veksler
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
Elena Kolevska
 
13.exemplu closure controller
13.exemplu closure controller13.exemplu closure controller
13.exemplu closure controller
Razvan Raducanu, PhD
 
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 Way
SmartLogic
 
Zend Framework 1.8 Features Webinar
Zend Framework 1.8 Features WebinarZend Framework 1.8 Features Webinar
Zend Framework 1.8 Features Webinar
Ralph 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 Symfony2
Sumy PHP User Grpoup
 
Rails engines in large apps
Rails engines in large appsRails engines in large apps
Rails engines in large appsEnrico Teotti
 
Laravel 101
Laravel 101Laravel 101
Laravel 101
Commit University
 
Redmine Betabeers SVQ
Redmine Betabeers SVQRedmine Betabeers SVQ
Redmine Betabeers SVQ
Ildefonso Montero
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJS
RajthilakMCA
 
Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2Laravel Beginners Tutorial 2
Laravel Beginners Tutorial 2
Vikas Chauhan
 

What's hot (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 to Simplify Your Rails Controllers With a Vengeance

More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
shaokun
 
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 Rails
Viget 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 API
cgmonroe
 
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 Know
Chris 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 Code
scidept
 
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
ManageIQ
 
Rails antipatterns
Rails antipatternsRails antipatterns
Rails antipatterns
Chul 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-public
Chul Ju Hong
 

Similar to 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
 

Recently uploaded

Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Tobias Schneck
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
91mobiles
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
Paul Groth
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
Alison B. Lowndes
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
Prayukth K V
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
Ralf Eggert
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 

Recently uploaded (20)

Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdfSmart TV Buyer Insights Survey 2024 by 91mobiles.pdf
Smart TV Buyer Insights Survey 2024 by 91mobiles.pdf
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMsTo Graph or Not to Graph Knowledge Graph Architectures and LLMs
To Graph or Not to Graph Knowledge Graph Architectures and LLMs
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........Bits & Pixels using AI for Good.........
Bits & Pixels using AI for Good.........
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 previewState of ICS and IoT Cyber Threat Landscape Report 2024 preview
State of ICS and IoT Cyber Threat Landscape Report 2024 preview
 
PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)PHP Frameworks: I want to break free (IPC Berlin 2024)
PHP Frameworks: I want to break free (IPC Berlin 2024)
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 

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