Ruby Anti-Pattern Variety Pack
I'm not really into patterns, but here are a few pieces of code that show up a lot but can be written another (arguably) better way.
Rescuing an Exception in a Method
How not to do it:
The 'begin' is unnecessary. The method can be implemented as:
Rescuing Any Exception
I doubled up on the last example. If you want to rescue any Exception, rather than:
write:
Update: I was wrong about this. Rescue without a class will only rescue up to StandardError, not Exception.
Selecting Some Elements out of a Collection
How not to write it:
This should be implemented using Enumerable#select. Enumerable is a good module to be familiar with. The better implementation:
Variable Assignment from If (or Case) Statement
Again, somebody may argue readability on this one, but I like it better. Rather than:
An if statement will return a value, so write the above section of code as:
Returning from an Iterator
Alright, one more Enumerable example. Most of the time if you write a piece of code that returns from an iterator, such as an .each loop, you're looking for a specific element in the collection. Rather than:
The detect method lives in the Enumerable module. It will return the first item in the collection which when passed to the block evaluates to true. If no items are found, .detect returns nil. This allows us to use || to return a default value if we need to.
Rescuing an Exception in a Method
How not to do it:
def some_method begin do_something rescue Exception => ex handle_exception(ex) end end
The 'begin' is unnecessary. The method can be implemented as:
def some_method do_something rescue Exception => ex handle_exception(ex) end
Rescuing Any Exception
I doubled up on the last example. If you want to rescue any Exception, rather than:
rescue Exception => ex
write:
rescue => ex
Update: I was wrong about this. Rescue without a class will only rescue up to StandardError, not Exception.
Selecting Some Elements out of a Collection
How not to write it:
odd_numbers = [] [1,2,3,4,5,6,7,8].each do |number| odd_numbers << number if number % 2 == 1 # note: with ActiveSupport in Rails, you could write: if number.odd? end
This should be implemented using Enumerable#select. Enumerable is a good module to be familiar with. The better implementation:
odd_numbers = [1,2,3,4,5,6,7,8].select { |number| number % 2 == 1 } #=> [1,3,5,7] # In Rails, this would work: odd_numbers = [1,2,3,4,5,6,7,8].select(&:odd?)
Variable Assignment from If (or Case) Statement
Again, somebody may argue readability on this one, but I like it better. Rather than:
if something_is_true? my_variable = :some_value else my_variable = :another_value end
An if statement will return a value, so write the above section of code as:
my_variable = if something_is_true? :some_value else :another_value end
Returning from an Iterator
Alright, one more Enumerable example. Most of the time if you write a piece of code that returns from an iterator, such as an .each loop, you're looking for a specific element in the collection. Rather than:
def my_method collection.each do |item| return item if item.right_one? end :item_not_found endYou can write:
def my_method collection.detect { |item| item.right_one? } || :item_not_found end
The detect method lives in the Enumerable module. It will return the first item in the collection which when passed to the block evaluates to true. If no items are found, .detect returns nil. This allows us to use || to return a default value if we need to.
Posted on 2007-04-10 | permalink | del.icio.us
Blog Archive
