gpt4 book ai didi

ruby-on-rails - ActiveModel 动态属性类型

转载 作者:行者123 更新时间:2023-12-05 08:11:01 31 4
gpt4 key购买 nike

是否可以在运行时决定哪种类型在 ActiveModel::Attributes 中转换属性?我有以下代码

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

我想根据 type 的分配值来决定如何转换 value 属性。我尝试使用自定义类型,但事实证明,在 #cast 方法中,您无权访问 MyModel 的底层实例(也可能是好东西,考虑到关注点分离)

我还尝试使用 lambda block ,假设 ActiveModel 可能看到一个响应 #call 并在运行时调用此 block 的对象(它没有):

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)

背景:type 来自 DB 字段,其中可以包含各种类,其功能远不止转换 Integer。

我可以只做一个 def value 并在那里构建自定义逻辑,但我多次需要这个并且我还使用其他 ActiveModel 功能,如验证、嵌套属性......所以我必须我自己负责集成。

所以也许有一种方法可以用 ActiveModel 本身来做到这一点。

最佳答案

您将值作为字符串存储在数据库中,因此 ActiveRecord 会将其作为字符串检索。您将需要手动转换它。 Rails 提供了这些方法,我相信您很熟悉:

"1".to_i => to integer => 1
"foo.to_sym => to symbol => :foo
"1".to_f => to float => "1.0"
123.to_s => to string => "123"
(1..10).to_a => to array => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

然后在您的模型中您可以:

def value
case type
when "Integer"
value.to_i
when "Float"
value.to_f
...
end

这可行,但我发现这种方法存在问题。你 decalre 一个名为 type 的属性,你可能会得到一些 Rails 的错误,提示 type 是 STI 的保留字,或者得到奇怪的错误,我建议你重命名

关于ruby-on-rails - ActiveModel 动态属性类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67136178/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com