Skip to content

Instantly share code, notes, and snippets.

@jbr
Created February 12, 2011 11:15
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save jbr/823701 to your computer and use it in GitHub Desktop.
Save jbr/823701 to your computer and use it in GitHub Desktop.
ruby 1.9.2 case-like switch
# 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