More control over enum in Rails 7.1

ActiveRecord::Enum in Rails have long been a convenient tool for representing a set of symbolic values within a model. However, using enum can sometimes lead to unexpected behavior, especially when it comes to the automatic generation of instance methods. For instance, consider an Order model with an enum for status:

class Order < ApplicationRecord
  enum status: [:pending, :processed]
end

Instance objects would have a convenient methods like order.pending?, order.processed?. One of common possible issues with generated instance methods might be naming conflicts. For example, if we need to add a new status persisted for our Order model.

class Order < ApplicationRecord
  enum status: [:pending, :processed, :persisted]
end

Simple adding it to the enum definition would lead to an ArgumentError:

You tried to define an enum named "status" on the model
"Order", but this will generate a instance method
"persisted?", which is already defined by Active Record.
(ArgumentError)

We can fix it by adding _prefix/_suffix option for the enum:

class Order < ApplicationRecord
  enum status: [:pending, :processed, :persisted], _prefix: true
end

But then we’ll have to update #pending?/#processed? usages to #status_pending?/#status_processed?.

With Rails 7.1 #

In Rails 7.1, a new option _instance_methods is introduced , allowing developers to opt-out of the automatic generation of instance methods for enums. When enum is defined with _instance_methods: false, Rails will no longer generate methods like pending?, processed?, etc.

class Order < ApplicationRecord
  enum status: [:pending, :processed, :persisted], _instance_methods: false
end

Now we can define custom methods tailored to the specific needs without worrying about conflicts with automatically generated enum methods.

Benefits #

  • Reduced Method Clutter: By disabling the automatic generation of enum methods, we can keep model interfaces cleaner and more focused.

  • Flexibility in Method Naming: With enum instance methods disabled, we have the freedom to name methods the way we want to make the codebase more expressive and easier to understand.

  • Avoidance of Method Name Conflicts: In scenarios where enum method names clash with existing or future method names in the model, disabling enum instance methods can prevent potential conflicts and bugs.

  • Improved Performance: By reducing the number of automatically generated methods, there may be a slight improvement in application performance, especially in cases where models have numerous enum attributes.


Dmitry Tsvetkov is a Software Engineer at JetThoughts. Follow him on LinkedIn or GitHub .

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories .