Faking it: enums in Ruby

by

Ruby doesn’t have enums and in Rails I sometimes need it. I’ve come out with my own way of doing after some trial and error. First I want to be able to access these enums as constants in a class, like:

Pizza::RAW
Pizza::COOKED
Pizza::BOXED
Pizza::DELIVERED
Pizza::EATEN

That’s actually quite easy:

class Pizza
  RAW = 1
  COOKED = 2
  BOXED = 3
  DELIVERED = 4
  EATEN = 5
end

If I’m storing those values on the database, I’d like to have my database be more readable, so, I just store strings:

class Pizza
  RAW = "raw"
  COOKED = "cooked"
  BOXED = "boxed"
  DELIVERED = "delivered"
  EATEN = "eaten"
end

That’s not very efficient and there are better ways these days. But it’s simple and premature optimization is the root of all evil. Anyway, back to Ruby, I’d like to be able to get a list of all possible enum values, to be able to populate selections for example:

class Pizza
  RAW = "raw"
  COOKED = "cooked"
  BOXED = "boxed"
  DELIVERED = "delivered"
  EATEN = "eaten"

  STATES = [RAW, COOKED, BOXED, DELIVERED, EATEN]
end

Simple enough except that it doesn’t follow DRY style. In Ruby we can do better:

class Pizza
  STATES = [
    RAW = "raw",
    COOKED = "cooked",
    BOXED = "boxed",
    DELIVERED = "delivered",
    EATEN = "eaten"
  ]
end

That defines the constant and since the result of RAW = "raw" is "raw" we can also add it to an array at the same time.

John, the manager of the Ruby Pizza Shop was concerned that some pizzas were devoured immediately and others took as long as 15 minutes. Decided to improve his business he started investigating the whole procedure and he noticed that as soon as the pizza left the kitchen, some cooks considered delivered and marked them as such. That was wrong so instead of doing a pizza-state training, he decided we should improve the UI. Let’s describe the state.

class Pizza
  STATES = [
    RAW = "raw",
    COOKED = "cooked",
    BOXED = "boxed",
    DELIVERED = "delivered",
    EATEN = "eaten"
  ]

  STATE_EXPLANATIONS {
    RAW => "The pizza is not a pizza yet, just a bunch of ingredients.",
    COOKED => "OMG! That smells good!",
    BOXED => "It's ready to go.",
    DELIVERED => "The pizza has been snatched out of the hands of a delivery boy.",
    EATEN => "The pizza is no more."
  }
end

Of course we can do better than that and merge it in one:

class Pizza
  STATE {
    (RAW = "raw") => "The pizza is not a pizza yet, just a bunch of ingredients.",
    (COOKED = "cooked") => "OMG! That smells good!",
    (BOXED = "boxed") => "It's ready to go.",
    (DELIVERED = "delivery") => "The pizza has been snatched out of the hands of a delivery boy.",
    (EATEN = "eaten") => "The pizza is no more."
  }
end

Stylistically I’m not a fan, but semantically, that’s dryer. Now, we can get the list of states like this:

Pizza::STATE.keys

Leave a Reply

You may also like:

If you want to work with me or hire me? Contact me

You can follow me or connect with me:

Or get new content delivered directly to your inbox.

Join 5,043 other subscribers

I wrote a book:

Stack of copies of How to Hire and Manage Remote Teams

How to Hire and Manage Remote Teams, where I distill all the techniques I've been using to build and manage distributed teams for the past 10 years.

I write about:

announcement blogging book book review book reviews books building Sano Business C# Clojure ClojureScript Common Lisp database Debian Esperanto Git ham radio history idea Java Kubuntu Lisp management Non-Fiction OpenID programming Python Radio Society of Great Britain Rails rant re-frame release Ruby Ruby on Rails Sano science science fiction security self-help Star Trek technology Ubuntu web Windows WordPress

I've been writing for a while:

Mastodon

%d bloggers like this: