-
-
Save SafeAF/19d72a6a6fb7b2d01d85cc5b7228b9cd to your computer and use it in GitHub Desktop.
ruby 1.9.2 case-like switch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# In response to: | |
# http://mlomnicki.com/ruby/tricks-and-quirks/2011/02/10/ruby-tricks2.html | |
# Ruby 1.9.2 has some neat stuff that lets us make a readable | |
# alternative case statement that calls each method in turn. | |
# 1.9.2 features used: | |
# * hashes are ordered in 1.9.2 | |
# * cool JSON-style hash syntax | |
# * concise lambda syntax | |
# here's the magic bit of code: | |
class Object | |
def switch( hash ) | |
hash.each {|method, proc| return proc[] if send method } | |
yield if block_given? | |
end | |
end | |
# The above code allows us to do this: | |
offer.switch( | |
available: -> { order.submit }, | |
cancelled: -> { order.reject }, | |
postponed: -> { order.postpone } | |
) { raise UnknownStateError.new } | |
# As I see it, the major advantage of this is that we aren't messing | |
# with any existing methods (Symbol#===), and we don't need an | |
# is(...). | |
# Of course, we could make it look more like a control structure by | |
# defining it on Kernel. I'm calling this #switch! so we don't | |
# collide with Object#switch, but you probably wouldn't have both. | |
module Kernel | |
def switch!( thing, hash, &blk ) | |
thing.switch hash, &blk | |
end | |
end | |
# Which would let us | |
switch!( offer, | |
available: -> { order.submit }, | |
cancelled: -> { order.reject }, | |
postponed: -> { order.postpone } | |
) { raise UnknownStateError.new } | |
#------------------------------------------------------------------- | |
# Here's a variant that doesn't take the default as a block, letting | |
# us skip the parens: | |
class Object | |
def switch( hash ) | |
hash.each do |method, proc| | |
return proc[] if method == :Default || send( method ) | |
end | |
end | |
end | |
offer.switch available: -> { order.submit }, | |
cancelled: -> { order.reject }, | |
postponed: -> { order.postpone }, | |
Default: -> { raise UnknownStateError.new } | |
# or: | |
class Kernel | |
def switch!( thing, hash ) thing.switch hash end | |
end | |
switch! offer, | |
available: -> { order.submit }, | |
cancelled: -> { order.reject }, | |
postponed: -> { order.postpone }, | |
Default: -> { raise UnknownStateError.new } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment