active_type icon indicating copy to clipboard operation
active_type copied to clipboard

Enums require a `<name>_for_database` method to be defined in Rails 6

Open chriscz opened this issue 3 years ago • 1 comments

Suppose an enum defined as follows:

class Payment < ActiveType::Object
  enum state: { stale: 0, loading: 1, failed: 2, ready: 3 }, _default: :stale
end

Then in Rails 6, the following errors

Payment.new.ready?

with

NoMethodError: undefined method `state_for_database' for #<Payment:0x00007fec45d30408>
activemodel (6.1.4.6) lib/active_model/attribute_methods.rb:469:in `method_missing'
activerecord (6.1.4.6) lib/active_record/enum.rb:235:in `public_send'
activerecord (6.1.4.6) lib/active_record/enum.rb:235:in `block in define_enum_methods' 

I did some preliminary investigation in the Rails source, but my time is limited right now. The issue definitely seems to be with the implementation of attribute. The fix in active_type could be as simple as aliasing the method to the "database" value.

  1. Call to attribute for enum is done here https://github.com/rails/rails/blob/571b4d5fb9cd254db79e93370d7b208b6d0fd1e4/activerecord/lib/active_record/attributes.rb#L276
  2. On a normal model, the _for_database method is defined by https://github.com/rails/rails/blob/571b4d5fb9cd254db79e93370d7b208b6d0fd1e4/activemodel/lib/active_model/attribute_methods.rb#L253
From: /home/chris/.rbenv/versions/2.7.4/lib/ruby/gems/2.7.0/gems/activemodel-6.1.4.6/lib/active_model/attribute_methods.rb:254:
Owner: DatabasePaymentModel::GeneratedAttributeMethods
Visibility: public
Signature: source_for_database(*args)
Number of lines: 3

CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
  attr_names.flatten.each { |attr_name| define_attribute_method(attr_name, _owner: owner) }
end

chriscz avatar Jul 20 '22 14:07 chriscz

Hi chriscz,

thank you for your report and the analysis. This seems to be a general issue for multiple Rails versions and active_type. We're currently unable to add support for enums in active_type objects ourselves, but if you'd open a PR for this feature we'd review it happily and merge it :)

NiklasHae avatar Aug 01 '22 07:08 NiklasHae