Rails 7.1 introduces a new option to exclude all custom methods generated by the ActiveRecord::Enum
ActiveRecord::Enum
is a feature introduced in Rails 4.1
that allows you to define attributes with a limited set of allowed values.
These values are stored as integers in the database
but can be accessed
and
manipulated by name within your Rails application.
To know more about Enum functionality, please refer to our previous blog post.
Before Rails 7.1
Defining an enum
in ActiveRecord automatically generates
several methods for querying,
manipulating,
and
accessing the enum values of a model instance.
Here's an example of how to define
and
use an enum for an Order status
attribute:
class Order < ApplicationRecord
enum status: { pending: 0, shipped: 1, completed: 2 }
end
# Access enum values
Order.statuses
=> { pending: 0, shipped: 1, completed: 2 }
order = Order.first
order.status
=> 'pending'
# Access integer equivalents
Order.statuses[:pending]
=> 0
order.status_value
=> 0
# Querying based on enum values
Order.shipped
SELECT "orders".* FROM "orders" WHERE "orders"."status" = $1 /* loading for pp */ LIMIT $2 [["status", 1], ["LIMIT", 11]]
# verify order values
order = Order.first
order.pending?
=> true
order.shipped?
=> false
# update order status
order.shipped!
Before Rails 7.1, if you want to turn off enums, there are workarounds and alternatives you can use:
1. Override generated methods:
You can manually override the generated methods in your model class. This approach requires more coding but gives you fine-grained control over the implementation.
class Order < ApplicationRecord
enum status: { pending: 0, shipped: 1, completed: 2 }
def pending?
status == :pending
end
def shipped!
update!(status: :shipped)
end
end
2. Use scopes instead of methods:
If you mainly use the generated methods for querying, consider using scopes instead. Scopes are more concise and efficient for filtering based on enum values.
class Order < ApplicationRecord
enum status: { pending: 0, shipped: 1, completed: 2 }
scope :pending, -> { where(status: :pending) }
scope :shipped, -> { where(status: :shipped) }
end
3. Use a Rails plugin:
Several plugins like enum_without_methods
and
rails_enum_without_methods
provide an easier way to
turn off enum method generation.
4. Use a custom enum implementation:
If you need advanced control over enum functionality, consider implementing your own enum solution without relying on the ActiveRecord methods.
Before Rails 7.1, when disabling methods, you had to be aware of potential side effects and ensure your code handles the enum values correctly.
In Rails 7.1
Rails 7.1 option to disable all methods that ActiveRecord.enum
generates.
You need to pass instance_methods: false
when declaring the enum
in the model.
class Order < ApplicationRecord
enum status: { pending: 0, shipped: 1, completed: 2 }, instance_methods: false
end
order = Order.first
order.pending?
=> `method_missing': undefined method `pending?' for #<Order id: "8de...
This feature is beneficial where the methods generated by the enum are conflicting, and most of the time, not all methods are required.
How disabling ActiveRecord Enums is helpful
** Improves performance:** By disabling the generation of dynamic methods, you can improve the performance of your application.
Reduces code size: Disabling enums can reduce the size of your application code, which can be beneficial in resource-constrained environments.
Provides more control: Disabling enums gives you more control over how you handle the enum values in your application.
Easier integration with external systems: By storing the enum values as integers, you can avoid any potential issues with data conversion when integrating with external systems.
To know more about this feature, please refer to this PR.