Rails 将临时属性合并到模型对象

Rails merge temporary attributes to model object

我有一个 Rails 模型对象,它的属性映射到数据库中的列。我计算了几个不在数据库列中的临时字段名称和年龄。有没有办法在不改变模型对象的情况下将它们暂时合并到对象中?

class MyModel < ApplicationRecord
end

我尝试使用 attributes.merge。并尝试过:

my_obj = my_obj.attributes.merge({ age: compute_age })

my_obj = my_obj.attributes.merge({ name: compute_name })

但是,第二次合并失败,出现 NoMethodError:#Hash:0x0000000120060010 的未定义方法“属性”。

看起来在我合并第一个对象的那一刻,它使对象成为哈希。所以我需要做

my_obj = my_obj.attributes.merge({ age: compute_age })

my_obj[:name]=compute_name

所有其他属性也作为哈希访问。 然而,这对我来说感觉不一致和奇怪!

是否有比使用 attributes.merge 更好的选择,即保留对象? 我想将 attr 添加到模型对象可能更清晰,但这些属性是临时的,不应在外部访问。

一旦你调用 .attributes 你就把 MyModel 实例变成了一个散列。

要将它变回模型,您只需将该散列传递给 MyModel 构造函数(假设您有一个 attr_accessor 作为虚拟属性):

my_obj = MyModel.new(my_obj.attributes.merge(age: compute_age))
my_obj = MyModel.new(my_obj.attributes.merge(name: compute_name))

您还可以在这里查看其他选项:Rails update_attributes without save?

编辑

再澄清一点。您可以通过 .attributes 将模型实例转换为散列。您可以使用 Model.new(attributes_hash) 将其 变回 模型。虽然它是一个散列,但您可以设置任何您想要的键值 - 它只是一个散列。但是为了将其转换回模型实例,您需要确保所有哈希键都对应于模型上的实际属性(它们是模式定义的持久属性,还是 attr_accessor 定义的虚拟属性) .

如果你只是想把它变成一个散列并在那里添加多个任意键值,你可以通过一次合并来完成:

attrs = my_obj.attributes.merge({ age: compute_age, name: compute_name })