ruby-on-rails - 如何从 ActiveRelation 更新选定 ActiveRecords 上的 `attr_accessor`
问题描述
介绍
假设我有一个attr_accessor
名为Book 的模型声明:purchased
。
class Book < ActiveRecord::Base
# contains fields like :id, :title, :description, :archived_at
...
attr_accessor :purchased
def purchased
@purchased || false
end
scope :unarchived, -> { where(archived_at: nil) }
...
end
问题
我有一个任意的方法
def mark_purchased(purchased_ids)
# 1. Returns ActiveRecord::Relation
unarchived_books = Book.unarchived
# 2. Mark only purchased books
purchased_books = unarchived_books.where(id: purchased_ids)
purchased_books.update_attr_accessor(purchased: true)
# 3. Return unarchived books with update :purchased attr_accessor
unarchived_books
end
此方法获取ActiveRecord::Relation
并更新attr_accessor
此关系的子集,然后应返回具有更新后的 attr_accessor 的整个关系
问题
如何以最少的代码量并尽可能高效地完成此任务?
假设我们有 200 000 本书,而用户只购买了 50 本书,我们暂时避免使用分页解决方案。我知道在显示它们时我将调用:purchased
200 000 次,但我只想更新unarchived_books
(具体为 50 条记录)的一个子集,而不是遍历所有书籍并检查它们是否在purchased_ids
.
我想到的最好的解决方案是
- 获取所有未归档的图书
- 获取一个子集并使用循环一个一个地更新它们(因为整体上
.each
没有什么比:update_attr_accessor
ActiveRecord::Relation
- 将这些关系合并在一起,用更新的关系覆盖第一个关系。
但是我的解决方案的第 3 个问题存在一个问题 - 该:merge
方法实际上忽略了attr_accessors
,所以我不知道从那里去哪里。
您对如何改进我的解决方案有任何提示吗?
解决方案
保证一个一个地加载和更新所有记录会用大量的数据耗尽内存。最快的方法是使用update_all
which 更新单个查询中的所有记录而不实例化它们:
def mark_purchased(purchased_ids)
purchased_books = Book.unarchived.where(id: purchased_ids)
purchased_books.update_all(purchased: true)
purchased_books
end
如果您真的必须一一更新它们,例如触发回调,请确保您使用批处理:
def mark_purchased(purchased_ids)
purchased_books = Book.unarchived.where(id: purchased_ids)
purchased_books.find_each do |book|
book.update(purchased: true)
end
purchased_books
end
尽管每个 UPDATE 查询都已发送到数据库,但这会慢一个数量级。
推荐阅读
- html - Flex / SCSS : Prev/Next 按钮左右对齐
- windows - 使用双引号在批处理 FOR 循环中传递多个参数?
- c# - RIchTextBox Rtf 编码
- html - HTML/CSS:为什么这些框不碰?
- ms-access - 运行时错误 3061 参数太少 预期错误 MS Access 365
- sharepoint - Graph API 从具有提升权限的 SPFx Webpart 创建组和团队
- android - Android HTTP 监听器
- javascript - 如何使用 JQuery 动态创建带有标签和复选框的表头
- java - 如何在 JAVA 中使用 Stream 来获取具有匹配值的对象?
- excel - 如何从垂直数据中水平查找数据?