Enums in Ruby

There are many ideas out there on how to represent enum values in Ruby. They seemed fun, but overall either too complex or missing something.

Here’s my approach.

# This lets you create convenient enums.
#
# Create a module to serve as a namespace for your enums, extend it with
# EnumModule and assign constants in it as usual.
#
# Example:
#
# module Status
#   extend EnumModule
#
#   OPEN = 1
#   CLOSED = 2
# end
#
# Status::OPEN # => 1
# Status.keys # => ['OPEN', 'CLOSED']
# Status.values # => [1, 2]
# Status.key(2) # => 'CLOSED'
# Status.include?('OPEN') # => true
module EnumModule
  def key(value)
    index = values.index(value)
    index && constants[index].to_s
  end

  def include?(key) = keys.include?(key)
  def keys = constants.map(&:to_s)
  def values = constants.map { const_get(_1) }
end

I’ve tried a few different ones, and settled on the above. It’s simple, flexible, and looks clean when applied in practice. I also like the idea of devoting the module/namespace to an enum, rather than having them loose in the surrounding module.

Why return names as strings instead of symbols?

I find that if I need these const names for anything, it’s usually some kind of display, JSON, or similar.


Code snippets in this post are covered by 0BSD License.



Date
October 5, 2024