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

Fetch ActiveRecord model for each key in array of hashes

我有一个散列数组,其中包含评论 ID 和他的标题:

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

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

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-query 会更好 类似于:

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 eager loading guide),这样我们就可以在不需要额外查询的情况下获取与评论相关联的用户:

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

从现在开始,您可以通过两种方式处理事情。先Enumerable#find (different than 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 and 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