Is it possible to decide which type casts an attribute in ActiveModel::Attributes
on runtime? I have the following code
class DynamicType < ActiveModel::Type::Value
def cast(value)
value # here I don't have access to the underlying instance of MyModel
end
end
class MyModel
include ActiveModel::Model
include ActiveModel::Attributes
attribute :value, DynamicType.new
attribute :type, :string
end
MyModel.new(type: "Integer", value: "12.23").value
I'd like to decide based on the assigned value of type
how to cast the value
attribute. I tried it with a custom type, but it turns out, inside the #cast
method you don't have access to the underlying instance of MyModel
(which also could be a good thing, thinking of separation of concerns)
I also tried to use a lambda block, assuming that maybe ActiveModel see's an object that responds to #call
and calls this block on runtime (it doesn't):
class MyModel
include ActiveModel::Model
include ActiveModel::Attributes
attribute :value, ->(my_model) {
if my_model.type == "Integer"
# some casting logic
end
}
attribute :type, :string
end
# => throws error
# /usr/local/bundle/gems/activemodel-5.2.5/lib/active_model/attribute.rb:71:in `with_value_from_user': undefined method `assert_valid_value' for #<Proc:0x000056202c03cff8 foo.rb:15 (lambda)> (NoMethodError)
Background: type
comes from a DB field and can have various classes in it that do far more than just casting an Integer.
I could just do a def value
and build the custom logic there, but I need this multiple times and I also use other ActiveModel features like validations, nested attributes... so I would have to take care about the integration myself.
So maybe there is a way to do this with ActiveModel
itself.