Ruby 数组适配器

Ruby array adapter

我必须查询一组来自不同来源的模型对象。每个来源returns一个Array with Hash like objects,但是同一模型(LogDoc)的布局不一样。

我的第一个方法是将查询结果对象包装到一个数组适配器中,该适配器基本上转换 #each 块中提取的每个元素。这是我想到的:

class MongoQueryAdapter
  extend Forwardable

  def initialize(mongo_query)
    @query_rows = mongo_query
    ...
  end

  def_delegators :@query_rows, ...

  def each(&block)
    @query_rows.each do |raw|
      log = LogDoc.new raw
      block.call(log)
    end
  end
end

这是我认为更适合我的用例的模式,但我担心性能,因为我听说 block.call产量.

是否可以使用 yield 来实现?或者性能影响真的值得考虑吗?

您可以 yield 而不是调用块,不需要其他更改。

def each
  if block_given?
    @query_rows.each do |raw|
      yield LogDoc.new(raw)
    end
  else
    # return Enumerator or raise
  end
end

看代码,我觉得你其实可以稍微简化一下:

def each(&block)
  @query_rows.map { |raw| LogDoc.new(raw) }.each(&block)
end

是的,yield 往往要快得多:

Calculating -------------------------------------
        bench_block    30.600k i/100ms
        bench_yield    42.073k i/100ms
-------------------------------------------------
        bench_block    768.311k (± 6.0%) i/s -      3.825M
        bench_yield      3.917M (± 2.8%) i/s -     19.564M