修改 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")); end
和def 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 属性仅用于保存的主要内容,如果未能解决你的问题,请参考以下文章