我有一个涉及块和传递它们的难题,需要帮助解决它

I have a conundrum involving blocks and passing them around, need help solving it

好的,所以我构建了一个 DSL,其中一部分要求 DSL 的用户定义我所谓的 'writer block'

  writer do |data_block|
    CSV.open("data.csv", "wb") do |csv|
      headers_written = false
      data_block do |hash|
        (csv << headers_written && headers_written = true) unless headers_written
        csv << hash.values
      end
    end
  end

writer 块是这样调用的:

  def pull_and_store
    raise "No writer detected" unless @writer
    @writer.call( -> (&block) {
      pull(pull_initial,&block)
    })
  end

问题有两个方面,首先,这是处理此类事情的最佳方式吗?其次,我遇到了一个奇怪的错误:

undefined method data_block' for Servo_City:Class (NoMethodError)

这很奇怪,因为我可以在那里看到 data_block,或者至少它存在于 CSV 块之前。

我正在尝试创建的是一种让用户编写包装器块的方法,该包装器块既可以包装一个块,又可以为正在包装的块生成一个块,哇,太啰嗦了。

内心的我不想在问题弄清楚之前写答案
其他我打赌代码示例将有助于澄清问题。


我假设写入块的任务是持久化一些数据。你能以可枚举的形式将数据传递到块中吗?这将允许 DSL 用户编写如下内容:

writer do |data|
  CSV.open("data.csv", "wb") do |csv|
    csv << header_row
    data.each do |hash|
      data_row = hash.values
      csv << data_row
    end
  end
end

不需要通过方块。

请注意,如果处理非常庞大的数据集,您可以传入一个 lazy 集合。

这是否解决了您的问题?

每次要写入记录时尝试打开 CSV 文件似乎过于复杂并且可能导致性能不佳(除非写入是间歇性的)。除非您将文件模式从 wb 更改为 ab

,否则每次它也会覆盖 CSV 文件

我觉得很简单,比如:

csv = CSV.open('data.csv', 'wb')
csv << headers
writer do |hash|
  csv << hash.values
end

会更容易理解。