为散列数组中的每个键获取ActiveRecord模型



我有一个带有注释id和标题的哈希数组:

arr = [{comment_id: 1, title: 'Title 1'}, {comment_id: 5, title: 'Title 2'}]

对于每个散列,我必须添加新的:密钥,其中包含活动记录模型作为值:

arr = [{comment_id: 1, user: #<User0x00007fd88dfe1b28>..., title: 'Title 1'},{comment_id: 5, user: #<User0x00005fd58dfe1a31>..., title: 'Title 2'}]

我发现的第一个解决方案是对每个哈希进行查询:

arr.each do |h|
h[:user] = Comment.find(h[:comment_id]).user
end

但是使用单个sql查询会更好类似于:

comment_ids = arr.map {|h| h[:comment_id] }
users = User.joins(:comments).order('comments.id').where(comments: {id: comment_ids })
# so here I need to match User with comment_id from comment_ids 

如果有人提出这样做的解决方案,那就太好了。

首先,我会找到与注释ID匹配的注释,还有includes(:user)(请参阅Rails热切加载指南(,这样我们就可以在不需要额外查询的情况下获得与注释相关联的用户:

comments = Comment.where(id: comment_ids).includes(:user)

从这一点上讲,你可以采取两种方式。首先是Enumerable#find(顺便说一句,不同于ActiveRecord::Base#find(,以挑选出与特定id对应的注释,然后从该注释记录中读取用户

arr.each do |h|
comment = comments.find { |comment| comment.id == h[:comment_id] }
h[:user] = comment.user
end

另一种方法是使用一些可枚举操作来创建哈希,其中键是注释ID,值是用户对象。参见index_by和transform_values

users_by_comment_id = comments.index_by(&:id).transform_values(&:user)
arr.each do |h|
h[:user] = users_by_comment_id[h[:comment_id]]
end