Enums are a great feature in Rails 4 – ActiveRecord’s native adoption of them is nearly worth the upgrade alone. However, I want to share a gotcha I came across today on a project I’m working on (the new version of tech startup simulator Hipster CEO if you must know).
I have a model Task in my schema that functions as an assignable piece of work to a member of staff. I’ve used the acts_as_relation gem to create a multi-table inheritance structure with things like TechTask, MarketingTask etc to assign to different departments. Each one of these subtasks will have a specific type (eg. frontend work, security analysis, testing etc. for a TechTask).
Therefore, each subtask will be of a specific type but these will vary from subtask to subtask. For example, you can’t create a TechTask with a type of “online_marketing”. Since this attribute is shared (admittedly with different key/value pairs) I thought it would be good practice to move it up to the parent Task model and then define the individual keys in the subclasses. And that’s precisely when things went wrong.
In order for the parent class Task to use the enums, they need to be defined in the parent class itself. Otherwise, when you create a subclass object, it will fail when you try to set the enum. Moving all the enums up a level pretty much defeats the purpose of having these subclasses, since they would be so tightly coupled.
In the end, I had to create an identical attribute on each subclass of Task and wrote generic helper methods for retrieval/inspection etc.
Of course, it’s debatable that inheriting enums is a correct approach at all (from my research online there was plenty of people strongly against it) but this does feel like a valid use case.
In summary, don’t inherit enums in Rails 4 because you’re gonna have a bad time.
UPDATE: Moving the enum down to the sub-class table means you can’t (AFAIK) create a composite index on the enum and whatever data you have in the parent table (in my case, it was an association id). Not the end of the world, but something to bear in mind all the same.