Skip to content

Instantly share code, notes, and snippets.

@ozydingo
Last active April 13, 2022 20:24
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 ozydingo/385455b565fb71f3dafd8b8116e5ba67 to your computer and use it in GitHub Desktop.
Save ozydingo/385455b565fb71f3dafd8b8116e5ba67 to your computer and use it in GitHub Desktop.
Enum in Ruby
# Slightly odd to inherit from Module; this lets us define consts such as FOOBAR::FOO
class Enum < Module
include Enumerable
attr_reader :values
delegate :each, to: :values
def initialize(&blk)
super(&nil) # Don't pass the block to super
@values = Set.new
# Define an EnumSet by passing a block to `new` with calls to `value`
instance_eval(&blk)
# Once the values are defined, we don't want the set to be modified.
@values.freeze
end
# Called during initialization to add values to the EnumSet
# After initialize, the set will be frozen, so you cannot call this afterwards.
def value(name, value = name)
const_set(name, value)
@values << value
end
end

EnumSet: define a quick enum instance with named consts

Usage: initialize a new EnumSet, passing a block declaring values:

FOOBAR = EnumSet.new do
  value "FOO"
  value "BAR"
end

This restuls in

FOOBAR::FOO -> "FOO"
FOOBAR::BAR -> "BAR"
FOOBAR.values -> ["FOO", "BAR"]

The returned intance is also an Enumerable, so you can iteratre on it directly using each, map, select, and so on.

All values must be valid const names.

If you wish to use values that differ from the names, simply use a second argument

FOOBAR = EnumSet.new do
  value "FOO", "foo"
  value "BAR", "wahoo"
end

This restuls in

FOOBAR::FOO -> "foo"
FOOBAR::BAR -> "wahoo"
FOOBAR.values -> ["FOO", "BAR"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment