Proposal: create a helper for ActiveRecord enum attributes for large tables (without DB column default)
Problem to solve
For large tables, adding a default value for columns is difficult or impossible. Adding ActiveRecord::Enum attributes for such columns is pretty verbose and is currently done with significant code duplication, e.g.
class AddGroupViewToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :group_view, :integer # `users` table is not the largest one but is a good example still
end
end
class User
DEFAULT_GROUP_VIEW = 'details'.freeze
enum group_view: { details: 1, security_dashboard: 2 }, _prefix: true
# need to override scope because NULL is now considered a default value as well as :details
scope :group_view_details, -> { where('group_view = ? OR group_view IS NULL', group_view[:details]) }
def group_view
super || DEFAULT_GROUP_VIEW # to provide a default value if NULL i.e. was not set for this record yet
end
end
Further details
One could suggest solving this problem with EnumWithNil, e.g.
class User
include EnumWithNil
enum_with_nil group_view: { details: nil, security_dashboard: 1 }
end
But, using nil (NULL) one of the peer values for the choice seems to be semantically incorrect. From another hand, a choice providing an unknown, undefined, or unavailable option is a proper candidate for enum_with_nil.
This proposal is for enum attributes where all values are semantically of the same value comparing to each other.
It's a debatable topic. This issue is created for discussion of the best and MVC approach to this problem.
Proposal
Adding a model concern with a helper method that will:
- Create an enum attribute with the same options supported by native
ActiveRecord::Enum.enummethod - Add a model instance getter for the default value of the enum attribute
- Redefine the model scope provided by
ActiveRecord::Enumfor fetching records with the default value of the attributes to includeNULLs
E.g.
class User
include EnumWithDefault
enum_with_default group_view: { details: 1, security_dashboard: 2 } # first value is considered default or one might add a default: option to the helper method
end
What does success look like, and how can we measure that?
GitLab Team and contributors are using the aforementioned concern for all new enum attributes without a column default value since such a concern is implemented and merged into master.