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