Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Refactor Like A Boss: A Few Techniques for Ever...
Search
PromptWorks
February 21, 2014
Programming
0
2.3k
Refactor Like A Boss: A Few Techniques for Everyday Ruby Hacking
Presented by Greg Sterndale.
http://promptworks.com
PromptWorks
February 21, 2014
Tweet
Share
More Decks by PromptWorks
See All by PromptWorks
PromptWorks Talk Tuesdays: Yvonne Chen 1/24/17 "Agile-Retros"
promptworks
0
86
PromptWorks Talk Tuesdays: Ray Zane 1/17/17 "Elixir Is Cool"
promptworks
0
99
PromptWorks Talk Tuesdays: Ray Zane 9/13/16 "Elixir Processes"
promptworks
0
3.5k
PromptWorks Talk Tuesdays: Dustin Ingram 8/30/16 "What is an ADR?"
promptworks
1
150
PromptWorks Talk Tuesdays: Dustin Ingram 8/23/16 "Detecting Asteroids with Neural Networks in TensorFlow"
promptworks
1
140
Getting to know Arel: Active Record's nerdy little brother
promptworks
1
120
Writing DSLs with Parslet - NYC.rb
promptworks
0
2.5k
Straight Up Rspec: A Neat Ruby BDD Tool
promptworks
0
46
Double Trouble: Clarity on Test Doubles
promptworks
0
2.4k
Other Decks in Programming
See All in Programming
ID管理機能開発の裏側 高速にSaaS連携を実現したチームのAI活用編
atzzcokek
0
210
まだ間に合う!Claude Code元年をふりかえる
nogu66
5
640
AIコーディングエージェント(skywork)
kondai24
0
150
ハイパーメディア駆動アプリケーションとIslandアーキテクチャ: htmxによるWebアプリケーション開発と動的UIの局所的適用
nowaki28
0
390
tparseでgo testの出力を見やすくする
utgwkk
1
190
Go コードベースの構成と AI コンテキスト定義
andpad
0
120
堅牢なフロントエンドテスト基盤を構築するために行った取り組み
shogo4131
8
2.3k
ViewファーストなRailsアプリ開発のたのしさ
sugiwe
0
430
俺流レスポンシブコーディング 2025
tak_dcxi
14
8.5k
【Streamlit x Snowflake】データ基盤からアプリ開発・AI活用まで、すべてをSnowflake内で実現
ayumu_yamaguchi
1
120
新卒エンジニアのプルリクエスト with AI駆動
fukunaga2025
0
200
モデル駆動設計をやってみようワークショップ開催報告(Modeling Forum2025) / model driven design workshop report
haru860
0
260
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Agile that works and the tools we love
rasmusluckow
331
21k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
Six Lessons from altMBA
skipperchong
29
4.1k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Designing Experiences People Love
moore
143
24k
The Art of Programming - Codeland 2020
erikaheidi
56
14k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
It's Worth the Effort
3n
187
29k
Transcript
Refactor Like A Boss a few techniques for everyday Ruby
hacking
Refactoring The process of changing code without modifying behavior
Ungoals of refactoring • Brevity for the sake of brevity
• To demonstrate mastery of Ruby or design patterns
Goals of refactoring • Improve readability • Improve maintainability •
Improve extensibility • Promote an expressive API • Reduce complexity
Ruby freebies
if 1 > 0 @foo = 'bar' else @foo =
'baz' end ! @foo # => 'bar' DRY Assignment
@foo = if 1 > 0 'bar' else 'baz' end
! @foo # => 'bar' DRY Assignment
@foo = case 1 when 0..1 'bar' else 'baz' end
! @foo # => 'bar' DRY Assignment
@foo = 1 > 0 ? 'bar' : 'qux' !
@foo # => 'bar' Ternary operator
def postive?(number) number > 0 ? 'yes' : 'no' end
! positive?(100) # => 'yes' Ternary operator
def foo? if @foo true else false end end Bang
bang
def foo? @foo ? true : false end Bang bang
def foo? !!@foo end Bang bang
if not @foo @foo = 'bar' end Conditional assignment
unless @foo @foo = 'bar' end Conditional assignment
@foo = 'bar' unless @foo Conditional assignment
@foo ||= 'bar' Conditional assignment
Parallel assignment @foo = 'baz' @bar = 'qux' # =>
"baz" # => "qux"
Parallel assignment @foo, @bar = 'baz', 'qux' # => ["baz",
"qux"] ! @foo # => "baz"
Multiple return def get_with_benchmark(uri) res = nil bench = Benchmark.measure
do res = Net::HTTP.get_response(uri) end return res, bench.real end ! @response, @benchmark = get_with_benchmark(@uri) # => [#<Net::HTTPOK 200 OK>, 0.123]
def my_safe_method begin do_something_dangerous() true rescue false end end Implied
begin
def my_safe_method do_something_dangerous() true rescue false end Implied begin
def self.likelihood_of_rain Hpricot::XML(weather_xml)/'probability-of-rain' rescue Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError return false end
! def self.likelihood_of_snow Hpricot::XML(weather_xml)/'probability-of-snow' rescue Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError return false end Exception lists
NET_EXCEPTIONS = [ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError ] ! def self.likelihood_of_rain
Hpricot::XML(weather_xml)/'probability-of-rain' rescue NET_EXCEPTIONS return false end ! def self.likelihood_of_snow Hpricot::XML(weather_xml)/'probability-of-snow' rescue NET_EXCEPTIONS return false end Exception lists
(1..5).map{|number| number.to_s } # => ["1", "2", "3", "4", "5"]
Symbol to Proc
(1..5).map(&:to_s) # => ["1", "2", "3", "4", "5"] Symbol to
Proc
def fibonacci_sum sum = 0 [1,1,2,3,5,8,13].each{|int| sum += int }
sum end ! fibonacci_sum() # => 33 MapReduce
def fibonacci_sum [1,1,2,3,5,8,13].reduce(0){|sum, int| sum + int } end !
fibonacci_sum() # => 33 MapReduce
{:foo => 'bar'}.inject({}) do |memo, (key, value)| memo[value] = key
memo end ! # => {"bar" => :foo} MapReduce
match_data = 'my lil string'.match(/my (\w+) (\w+)/) match_data.captures[0] # =>
"lil" match_data.captures[1] # => "string" match_data.captures[2] # => nil Regex captures
'my lil string'.match(/my (\w+) (\w+)/) $1 # => "lil" $2
# => "string" $3 # => nil Regex captures
'my lil string' =~ /my (\w+) (\w+)/ $1 # =>
"lil" $2 # => "string" $3 # => nil Regex captures
def Resource.create resource = Resource.new resource.save resource end # =>
#<Resource:0xffffff> tap
def Resource.create Resource.new.tap{|resource| resource.save } end # => #<Resource:0xffffff> tap
sprintf("%d as hexadecimal: %04x", 123, 123) # => "123 as
hexadecimal: 007b" ! "%d as hexadecimal: %04x" % [123, 123] # => "123 as hexadecimal: 007b" ! "%s string" % ['my'] # => "my string" sprintf
def cerealize(val) if val.is_a?(Numeric) || val.is_a?(String) val elsif val.is_a?(Enumerable) val.to_json
else val.to_s end end case equality
def cerealize(val) case val when Numeric, String val when Enumerable
val.to_json else val.to_s end end case equality
if command =~ /sudo/ raise 'Danger!' elsif command =~ /^rm
/ puts 'Are you sure?' else puts 'Run it.' end case equality
case command when /sudo/ raise 'Danger!' when /^rm / puts
'Are you sure?' else puts 'Run it.' end case equality
Splat Array def shopping_list(ingredients) unless ingredients.is_a?(Array) ingredients = [ingredients] end
ingredients.join(", ") end ! shopping_list("eggs") # => "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon"
Splat Array def shopping_list(ingredients) [ingredients].flatten.join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! !
Splat Array def shopping_list(ingredients) [*ingredients].join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! !
Splat args def shopping_list(*ingredients) ingredients.join(", ") end ! shopping_list("eggs") #
=> "eggs" shopping_list(["eggs", "bacon"]) # => "eggs, bacon" ! shopping_list("eggs", "bacon") # => "eggs, bacon"
Rails freebies
if @user.name and
[email protected]
? puts @user.name else puts "no name"
end blank?
if @user.name.blank? puts "no name" else puts @user.name end blank?
if @user.name.present? puts @user.name else puts "no name" end present?
puts @user.name.presence || "no name" presence
truncate opening = "A long time ago in a galaxy
far, far away" if opening.size > 20 opening[0..16] + "..." end # => "A long time ago i..."
truncate opening = "A long time ago in a galaxy
far, far away" opening.truncate(20) # => "A long time ago i..." !
truncate opening = "A long time ago in a galaxy
far, far away" opening.truncate(20, :separator => ' ') # => "A long time ago..." !
@existing = User.find_by_email(@new.email) @existing.destroy if @existing try
User.find_by_email(@new.email).try(:destroy) try
in? if admin_roles.include? @user.role puts "Hi Admin!" end
in? if @user.role.in? admin_roles puts "Hi Admin!" end
class User ! has_one :account ! def balance self.account.balance end
! def balance=(amount) self.account.balance=(amount) end ! end Delegation
class User ! has_one :account ! delegate :balance, :balance=, :to
=> :account ! end Delegation
class Avatar ! def file_size if @file_size return @file_size else
result = some_expensive_calculation result += more_expensive_calculation @file_size = result end end ! end Memoization
class Avatar ! extend ActiveSupport::Memoizable ! def file_size result =
some_expensive_calculation result += more_expensive_calculation end memoize :file_size ! end Memoization
! alias_method :translate_without_log, :translate ! def translate_with_log(*args) result = translate_without_log(*args)
Rails.logger.info result result end ! alias_method :translate, :translate_with_log alias_method_chain
def translate_with_log(*args) result = translate_without_log(*args) Rails.logger.info result result end !
alias_method_chain :translate, :log alias_method_chain
class Resource class < self ! def host=(name) @host =
hame end def host @host end ! end end class_attribute
class Resource class < self ! attr_accessor :host ! end
end class_attribute
class Resource ! class_attribute :host ! end class_attribute
Hash#symbolize_keys my_hash = { 'foo' => 123 }.symbolize_keys my_hash['foo'] #
=> nil my_hash[:foo] # => 123
Hash#stringify_keys my_hash = { :foo => 123 }.stringify_keys my_hash['foo'] #
=> 123 my_hash[:foo] # => nil
HashWithIndifferentAccess my_hash = { :foo => 123 } my_hash['foo'] #
=> nil my_hash[:foo] # => 123
HashWithIndifferentAccess my_hash = { :foo => 123 }.with_indifferent_access my_hash['foo'] #
=> 123 my_hash[:foo] # => 123
forty_two my_array = [] my_array[41] = "the answer" ! my_array[41]
# => "the answer"
forty_two my_array = [] my_array[41] = "the answer" ! my_array.forty_two
# => "the answer"
slideshare github irc gsterndale gsterndale sternicus