-
Notifications
You must be signed in to change notification settings - Fork 22k
Introduce ActiveModel::Enum
#49872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce ActiveModel::Enum
#49872
Conversation
bfed7bd
to
d0a9a46
Compare
cc @jonathanhefner and @ghiculescu who are probably interested in AM::Enum and would be good to get their feedback 🙏 |
activemodel/lib/active_model/attribute_methods/before_type_cast.rb
Outdated
Show resolved
Hide resolved
e031a7e
to
e5b884c
Compare
Allow ActiveRecord::Enum to be mixed in with include instead of extend, like most other ActiveModel inherited modules. This refactoring makes it easier to move `ActiveRecord::Enum` to `ActiveModel::Enum` and mixin `ActiveModel::Enum` with include instead of `extend`.
This moves most of the implementation of ActiveRecord::Enum to ActiveModel::Enum. This excludes: * scopes, as scopes aren't supported by ActiveModel. * method conflict detection, as this is difficult to implement in ActiveModel. ```ruby class Conversation include ActiveModel::Attributes include ActiveModel::Enum attribute :status, :integer enum :status, [ :active, :archived ] end conversation = Conversation.new conversation.active! conversation.active? # => true conversation.status # => "active" ``` The current implementation supports using integers for values and strings for labels, if defined. The tests were copied from ActiveRecord and modified for ActiveModel. Scoping and method conflict detection tests were excluded.
Thank you for the pull request. I didn't want Enum to be added to Active Record. For sure I'll not let it be added to Active Model. There is no reason to translate strings to integer in the active model layer. There is no benefits on doing that. I can see the benefits in Active Record. |
Hi @rafaelfranca, I don't care about the mapping of integers to strings either. Keeping that in place just made the PR easier/smaller. My main reason for an ActiveModel::Enum is to replace code like the following: class SomeModel
module States
STARTED = 'started'
DONE = 'done'
FAILED = 'failed'
ALL = constants(false).map { |constant| const_get(constant) }
end
attribute :state, String
validates :state, inclusion: { in: States::ALL }
def started?
state == States::STARTED
end
def done?
state == States::DONE
end
def failed?
state == States::FAILED
end
def state=(value)
raise ArgumentError, "'#{value}' is not a valid state" unless States::ALL.include?(value)
super
end
end With something like: class SomeModel
attribute :state, String
enum :state, [:started, :done, :failed]
end Would you be open to an ActiveModel::EnumType? class SomeModel
attribute :state, :enum, [:started, :done, :failed]
end |
That is exactly my problem with A type is an interesting idea, but not sure it solve the problem you are trying to solve. Types don't generate methods. Neither do validation, they usually make invalid values |
This moves most of the implementation of ActiveRecord::Enum to
ActiveModel::Enum. This excludes:
ActiveModel.
The current implementation supports using integers for values and
strings for labels, if defined.
This also introduces ActiveSupport::Concern to ActiveRecord::Enum as
this allows both ActiveModel::Enum and ActiveRecord::Enum to be mixed in
with
include
instead ofextend
, like most other ActiveModel modules.The tests were copied from ActiveRecord and modified for ActiveModel.
Scoping and method conflict detection tests were excluded.
Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]