DEV Community

Cover image for More control over enum in Rails 7.1
JetThoughts Dev for JetThoughts

Posted on • Edited on • Originally published at jetthoughts.com

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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

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

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
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (3)

Collapse
 
pimp_my_ruby profile image
Pimp My Ruby

If you don't want the instances methods, why would you use enum ?

Collapse
 
pftg profile image
Paul Keen

There are other helpers generated for example scopes. So sometimes you need only them.

Collapse
 
jetthoughts-dev profile image
JetThoughts Dev

We might want to utilize other quite useful generated things like scopes & validation.