我想转换ActiveRecord::Relation
个对象的嵌套数组,如下所示:
# Event is a ActiveRecord::Base derived class
r1 = [ [ Event.where(id: 1) ], Event.where(id: 1)]
# => [ [ #<ActiveRecord::Relation []> ], #<ActiveRecord::Relation[]> ]
成:
[#<ActiveRecord::Relation []>, #<ActiveRecord::Relation []> ]
Array#flatten
旨在完美地完成此任务。不幸的是,它没有返回预期的结果:
r1.flatten # => []
Enumrable#map
也不起作用:
r1.map{|m| m.limit(10) } # => []
Enumerable#flat_map
会返回一个不同的结果:
r1.flat_map{|m| m.limit(10) } # => [ #<ActiveRecord::Relation []> ]
最后,循环遍历数组并推入另一个空数组会返回预期结果:
z = []
r1.each {|e| if e.is_a?(Array) then e.each{|x| z << x} else z << e end}
# => [#<ActiveRecord::Relation []>, #<ActiveRecord::Relation []> ]
导致这些差异的原因是什么?
我正在使用
答案 0 :(得分:2)
你得到的结果是因为当你枚举关系(或将它转换为数组)时,它不包含任何元素。
您可以在关系的打印输出中看到这一点,该关系在[]
之前有>
。如果其中有任何内容,您可以看到括号内的元素。
答案 1 :(得分:2)
当您执行.flatten
时,该方法将触发由要执行的Relations包装的SQL查询。然后,查询结果将被展平。
在您的情况下,看起来两个查询都返回了一个空记录集,导致
r1 = [ [ Event.where(id: 1) ], Event.where(id: 1)]
评估为
r1 = [ [[]] , []]
该缩进变平为
[]
如果您尝试使用产生结果的范围的代码,那么您将看到flatten将返回记录数组。
为了展平范围,您需要一个像您一样的自定义方法。这是一个与illimitate级别一起使用的增强版本。
def flatten_scopes(scopes)
scopes.inject([]) { |a,r| r.is_a?(Array) ? a += flatten_scopes(r) : a.push(r) }
end
flatten_scopes(r1)