A little background first. I've been working on a fairly large Rails application which quickly grew into a breeding ground for "smelly" code. One antipattern we were using a lot was storing objects in an STI lookup table and having lots of scattered logic based on the name of the object.
Here's a dumbed down example of what we had:
class Lookup < ActiveRecord::Base end class AlarmStatus < Lookup has_many :alarm_logs end class AlarmLog < ActiveRecord::Base belongs_to :alarm_status end
Then all over our application we would do things like:
case @alarm_log.alarm_status.name when "active" # Do something when "verified" # Do something when "inactive" # Do something end
This is obviously bad for a lot of reasons, but let's just say it was everywhere. After a few months of this, a consultant came along and pointed out our "code smell" and made some suggestions on how to refactor, which included a Ruby implementation of Java's Enum class.
We ended up using this frequently in our app, and have extracted into a ruby gem called classy_enum. The premise of classy_enum is that you get the power of OOP mixed with the strictness of an enumerated type, which is pretty much what we were trying to mimic with our STI Lookup model.
Example of defining an enum:
class Priority < ClassyEnum::Base enum_classes :low, :medium, :high def send_email? false end end class PriorityHigh < Priority def send_email? true end end
The gem's README has some other usage examples, including how to integrate it with a Rails project.
I may be asking for a lot here, but I would love some feedback from anyone willing to give it. It seems like a really cool solution to our problem and I can't imagine we're the only ones who have attempted to solve this before. Here's a list of questions that would be really useful for us:
- Is this a common problem?
- Does our solution make sense? Is there a better way to do it?
- Is the documentation clear?
- Would you use this in your application? Why or why not?
- How could we improve it?
- How is the code quality?