ruby-on-rails - 将从序列化中恢复的 ActiveRecord 项标记为持久性
问题描述
我有一种情况,已知在数据库中的一组项目是从序列化的 json 数组中恢复的,包括它们的id,因此可以将它们重塑为仅调用 new 的 ActiveRecord 模型实例,而无需访问数据库:
for itm in a do
item = Item.new(itm)
itmlist << item
emd
现在,问题是,如何告诉 ActiveRecord 这些元素已经持久化而不是新元素?如果item.new_record?
为真,aitem.save
将失败,因为 Rails 将插入而不是更新。
目标是确保 Rails 确实更新,而不需要对数据库进行任何额外查询。我得到的最接近的是
item = Item.new(itm)
item.instance_variable_set(:@new_record, false)
使用 ActiveRecord Internals 播放
解决方案
不确定我是否完全理解这个问题,但如果您只想更新所有项目,以下内容将起作用
a.each do |item_hash|
Item.find(item_hash["id"]).update(item_hash.except("id"))
end
如果Item
可能存在或可能不存在,那么
a.each do |item|
item = Item.find(item_hash["id"]) || Item.new
item.update(item_hash.except("id"))
end
这些选项中的任何一个都不会处理验证失败。根据您的使用情况,以下可能有用
all_items = a.map do |item_hash|
item = Item.find(item_hash["id"]) || Item.new
item.assign_attributes(item_hash.except("id"))
end
pass,fail = all_items.partition(&:save)
如果您只关心失败,您可以将其更改为:fail = all_items.reject(&:save)
如果有大量的项目,那么还有更多的替代方案可以避免如此多的查询。例如Item.where(id: a.map {|i| i["id"]})
推荐阅读
- python - 使用 pyinstaller 执行脚本 myfile.py 失败
- javascript - 为什么这个按钮不能点击?
- java - Corda 帐户转移状态流问题
- c - 如何充当客户端和服务器之间的代理?
- javascript - (if) 条件的新值无效
- reactjs - Office UI Fabric / Fluent UI React Charts 的官方文档和示例?
- operating-system - 为什么大多数 posix 命名对象都设计为取消链接?
- docker - 无法将 Hyperledger Explorer 连接到 Fabric 项目
- java - 从 Spring Boot REST API 重定向到分离的反应前端
- shell - 如何在组织模式片段中显示 inxi 输出