我有一个查询*,结果如下:
#<ActiveRecord::Relation [
#<BookRank id: 2, book_id: 2, list_edition_id: 1, rank_world: 5, rank_europe: 1>,
#<BookRank id: 3, book_id: 1, list_edition_id: 1, rank_world: 6, rank_europe: 2>,
#<BookRank id: 8, book_id: 2, list_edition_id: 3, rank_world: 1, rank_europe: 1>,
#<BookRank id: 9, book_id: 1, list_edition_id: 3, rank_world: 2, rank_europe: 2
]>
我想要得到的是这样的哈希:
{
book_id => {
list_edition_id => {
"rank_world" => value,
"rank_europe" => value
}
}
}
(最重要的是按照最低list_edition_id的rank_world值对哈希进行排序,但这也许太复杂了。)
ranks_relation.group_by(&:book_id)
给了我一个哈希,其中book_ids
是键,但是rank数据仍然在数组中:
{
2 => [
#<BookRank id: 2, book_id: 2, list_edition_id: 1, rank_world: 5, rank_europe: 1>,
#<BookRank id: 8, book_id: 2, list_edition_id: 3, rank_world: 1, rank_europe: 1>
],
1 => [
#<BookRank id: 3, book_id: 1, list_edition_id: 1, rank_world: 6, rank_europe: 2>
#<BookRank id: 9, book_id: 1, list_edition_id: 3, rank_world: 2, rank_europe: 2>
]
}
我应该如何进行?
* EDIT::这是模型结构和查询。另一个用户要求它:
class Book < ActiveRecord::Base
has_many :book_ranks, dependent: :destroy
end
class List < ActiveRecord::Base
has_many :list_editions, dependent: :destroy
end
class ListEdition < ActiveRecord::Base
belongs_to :list
has_many :book_ranks, dependent: :destroy
end
class BookRank < ActiveRecord::Base
belongs_to :book
belongs_to :list_edition
has_one :list, through: :list_edition
end
对于查询,我已经使用两个具有Book
和ListEdition
相关ID的数组:
BookRank.where(:book_id => book_ids, :list_edition_id => list_edition_ids)
答案 0 :(得分:2)
尝试一下
record = your_record
hash = {}
record.each do |record|
hash[record.book_id] ||= {}
hash[record.book_id][record.list_edition_id] = {
'rank_world' => record.rank_world,
'rank_europe' => record.rank_europe
}
end
# hash will then be {2=>{1=>{"rank_world"=>5, "rank_europe"=>1}, 3=>{"rank_world"=>1, "rank_europe"=>1}}, 1=>{1=>{"rank_world"=>6, "rank_europe"=>2}, 3=>{"rank_world"=>2, "rank_europe"=>2}}}
这只会遍历记录一次。
答案 1 :(得分:1)
嘿@gibihmruby(名字叫btw),
因此,由于您在评论中要求使用group_by
和朋友对我的丑陋方法进行更具体的描述,因此,我的建议是
rel.group_by(&:book_id).map do |k, v|
[k, v.group_by(&:list_edition_id)]
end.to_h
将产生类似
的结构{2=>
{1=>
[#<struct BookRank
id=2,
book_id=2,
list_edition_id=1,
rank_world=5,
rank_europe=1>],
3=>
[#<struct BookRank
id=8,
book_id=2,
list_edition_id=3,
rank_world=1,
rank_europe=1>]},
1=>
{1=>
[#<struct BookRank
id=3,
book_id=1,
list_edition_id=1,
rank_world=6,
rank_europe=2>],
3=>
[#<struct BookRank
id=9,
book_id=1,
list_edition_id=3,
rank_world=2,
rank_europe=2>]}}
然后,您必须将最内部的对象映射到所需的属性。如果您确定book_id
和list_edition_id
的组合是唯一的,则可以摆脱数组包装,然后映射到所需的属性。您可以将slice用于ActiveRecord
对象。映射将是
rel.group_by(&:book_id).map do |book_id, grouped_by_book_id|
[
book_id,
grouped_by_book_id.group_by(&:list_edition_id).map do |list_ed_id, grouped|
[list_ed_id, grouped.first.slice(:rank_world, :rank_europe)]
end.to_h
]
end.to_h
由于我不是创建模型而是仅使用结构(如您在上面的示例中看到的那样),所以我并没有真正自己测试最后一点。但是它应该像这样工作,如果发现错误或有其他问题,请发表评论。我仍然希望有人提出一个更好的解决方案,因为我现在太想自己了。
干杯:)
编辑:较小的更正
答案 2 :(得分:0)
ranks_relation.
group_by(&:book_id).
map do |id, books|
[id, books.map do |book|
[
book.list_edition_id,
{
"rank_world" => book.rank_world,
"rank_europe" => book.rank_europe
}
]
end.sort_by { |_, hash| hash["rank_world"] }.to_h
]
end.to_h