Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

option.rb is an attempt to duplicate the functionality of Scala's Option class in Ruby

branch: master

Fetching latest commit…


Cannot retrieve the latest commit at this time

Octocat-spinner-32 option.rb


Because nil stinks and I'm tired of NoMethodError: undefined method '[]' for nil:NilClass


An Option is either the singleton None or an instance of Some:

s = Some(1)
s == Some(1) # true
s != None    # true

Both None and instances of Some have the standard collection methods (including filter, for those of you who agree with me that select is a stupid name):

s.each {|i| i + 1}   # 2 {|i| i + 1}    # Some(2)
s.filter {|i| i > 1} # None

To get the raw values:

s.get # 1
s.each {|i| i} # 1
None.get # RuntimeError: None has no value

Because of this, it's best to give a default:

s.getOrElse(2)    # 1
None.getOrElse(2) # 2

Blocks are supported for lazy loading the default:

s.getOrElse {|| slow_calculation} # 1, slow_calculation is never done
None.getOrElse {|| slow_calculation} # result of slow_calculation

The Option() method is a good way to get an Option. Any value is converted to Some(value), while nil is converted to None:

result      = Option(some_method_that_might_return_nil("something"))
transformed = result.filter{|i| i > 2}.map{|i| i.to_s}
puts filtered.getOrElse("default")

If nil is bad, so are exceptions. Eat them with tryo:

result      = tryo {|| raise "silly error" }
transformed = result.filter{|i| i > 2}.map{|i| i.to_s}
puts filtered.getOrElse("default") # will be "default"

If you start using lots of Options you might want to flatten them with flatMap: {|id| get_user_from_db(id) }      # Some(Some(User #1 ...))
s.flatMap {|id| get_user_from_db(id) }  # Some(User #1 ...)

The block passed to flatMap must return an Option:

id = Some("unknown id")
id.flatMap {|id| get_user_from_db(id) } # None
id.flatMap {|id| id}                    # RuntimeError: Did not return an Option
Something went wrong with that request. Please try again.