Skip to content

Instantly share code, notes, and snippets.

@sinsoku
Last active June 23, 2020 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sinsoku/7e146ef301a059d2cb2c1f6a63013a74 to your computer and use it in GitHub Desktop.
Save sinsoku/7e146ef301a059d2cb2c1f6a63013a74 to your computer and use it in GitHub Desktop.
A gem for finding non-exhaustive case statements.
module CaseMatch
class Error < StandardError; end
class Case
EMPTY_BLOCK = -> {}
def initialize(obj, cases)
@obj = obj
@cases = cases
@values = []
@blocks = []
end
def when(*values, &block)
@values |= values
if values.any? { |v| @obj === v }
@blocks << block || EMPTY_BLOCK
end
self
end
def else(&block)
@values = @cases
@blocks << block || EMPTY_BLOCK
self
end
def esac
raise Error if @cases != @values
@blocks.first.call
end
alias :end :esac
end
end
class User
def case(attr)
CaseMatch::Case.new(public_send(attr), statuses.keys)
end
# Simulate ActiveRecord::Enum
def status
"active"
end
def statuses
{ "active" => 0, "archived" => 1 }
end
end
user = User.new
user.case(:status)
.when("active") { puts "active" }
.when("archived") { puts "archived" }
.end
#=> "active"
user = User.new
user.case(:status)
.when("active") { puts "active" }
.when("archived")
.end
#=> "active"
user = User.new
user.case(:status)
.when("active") { puts "active" }
.end
#=> CaseMatch::Error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment