修改 ActiveRecord 属性仅用于保存

Posted

技术标签:

【中文标题】修改 ActiveRecord 属性仅用于保存【英文标题】:Modify ActiveRecord attribute only for saving 【发布时间】:2022-01-17 23:59:08 【问题描述】:

假设我有一些 ActiveRecord 实例。我怎样才能让rails在它保存在数据库中之前映射它的一个字段,但不改变内存中记录的值?before_save回调似乎修改值不仅仅是为了保存它。

此示例通过将字段 n 映射到 n -> n*2(可逆映射器)来显示所需的行为

x = MyRecord.create(n: 2)
x.n
=> 2
x.save()   # database should now contain value 4 in col n
x.n
=> 2       # value is still 2 (map only affects values in db)

更具体地说,我想使用 Marshal.dump 和 Marshal.load 来(反)序列化我的记录字段,以便数据库将它们包含为 blob。

【问题讨论】:

不确定我是否理解这里的意图。重新加载此记录的期望是什么,例如x = MyRecord.find(x_id)n 应该是 2 还是 4?也许您已经过度混淆了这个问题,因为您说“更具体地说,我想使用 Marshal.dump 和 Marshal.load 来(反)序列化字段”,这完全不同。也许您只是在寻找def n; Marshall.load(read_attribute("n")); enddef n=(val); write_attribute("n",Marshall.dump(val)); end “我想使用 Marshal.dump 和 Marshal.load 来(反)序列化我的记录字段,以便数据库将它们包含为 blob”,不要这样做。当您升级 Ruby 时,marshal 格式可能会发生变化,并且没有简单的方法可以读取旧格式。你最好存储规范化数据而不是序列化数据,或者使用像 JSON 这样的稳定​​格式,甚至可能使用支持 JSON 列的数据库。 【参考方案1】:

在您的代码中,MyRecord.create(n: 2) 实际上会将记录保存到数据库中。

如果你想使用自定义的序列化(例如到 Marshall 之间的存储和内存格式的字段)。然后您可以使用自定义值类型,请参阅:https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html(在创建自定义类型下)。

【讨论】:

感谢自定义类型的提示。这很有帮助。我设法按照@mu-is-too-short 的建议以自定义类型将我的 Array 转换为 Json 数据来实现序列化

以上是关于修改 ActiveRecord 属性仅用于保存的主要内容,如果未能解决你的问题,请参考以下文章

保存 Rails 模型的所有属性

防止实例上的 ActiveRecord save()

Rails“多重继承”模型-具有另一个类的属性的ActiveRecord对象?

仅列出 ActiveRecord 子类方法

PyQt:通过样式表的属性仅用于绘画?

ActiveRecord 何时会保存关联?