ActiveRecord::Enum initialized with hash or array?

ActiveRecord::Enum initialized with hash or array?

Problem Description:

Let’s say we have this simple model:

class Project < ApplicationRecord
  enum stage: {Idea: "idea", Done: "done", "On hold": "on hold", Cancelled: "cancelled"}
  enum status: [:draft, :published, :archived]

When we access the enums from the model (Project.stages, Project.statuses) we get as result an processed (by ActiveRecord::Enum) response, both as a hash.

irb(main):001:0> Project.stages
=> {"Idea"=>"idea", "Done"=>"done", "On hold"=>"on hold", "Cancelled"=>"cancelled"}
irb(main):002:0> Project.statuses
=> {"draft"=>0, "published"=>1, "archived"=>2}

I’m struggling to know when an enum was declared as a Hash or as an Array having only the model and the enum name.

Any idea on how to get the initial hash or array from an enum?

Solution – 1

You should not be treating them differently due to the principle of least suprise.

enum status: [:draft, :published, :archived] is just an implicit shorthand for defining an enum where the mapping is the same as the indices of the array. That’s how its documented and having your code do something else opens up for a real WTF moment.

Defining enums implicitly is also regarded as a bad practice since adding new statuses in the middle of the array will break your application in a very sneaky way. There is even a Rubocop cop that detects the use of arrays by using a regular expression on the source code.

Its actually just a sloppy way of writing enum status: { draft: 0, published: 1, archived: 2}. You shouldn’t be encouraging its use.

The arguments you pass to enum are just used to metaprogram the setters, getters and create the metadata which stores the enum mapping. It doesn’t store the original arguments as there is no point to that.

If you REALLY wanted to do this you could monkeypatch the enum method:

module WonkyEnum
  # this is silly. Don't do this
  def enum(definitions)
    @_enum_definitions ||= []

But whatever the real problem is here there is most likely a better solution.

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.