ruby /生成器 API : create XML without using blocks

标签 ruby xml builder

我想使用Builder基于 ActiveRecord 模型表构造一组 XML 文件。我有近一百万行,因此我需要使用 find_each(batch_size: 5000) 迭代记录并为每批记录编写一个 XML 文件,直到记录耗尽。类似于以下内容:

filecount = 1
count = 0
xml = ""
Person.find_each(batch_size: 5000) do |person|
  xml += person.to_xml  # pretend .to_xml() exists 
  count += 1       

  if count == MAX_PER_FILE
    File.open("#{filecount}.xml", 'w') {|f| f.write(xml) }
    xml = ""
    filecount += 1
    count = 0
  end
end

这不适用于 Builder 的界面,因为它希望在 block 中工作,如下所示:

xml = builder.person { |p| p.name("Jim") }

一旦 block 结束,Builder 就会关闭其当前节;你不能保留对 p 的引用并在 block 之外使用它(我尝试过)。基本上,Builder 希望“拥有”迭代。

因此,为了使构建器能够使用此功能,我必须执行以下操作:

  filecount = 0
  offset = 0
  while offset < Person.count do
    count = 0
    builder = Builder::XmlMarkup.new(indent: 5)
    xml = builder.people do |people|
      Person.limit(MAX_PER_FILE).offset(offset).each do |person|
        people.person { |p| p.name(person.name) }
        count += 1
      end
    end

    File.open("#output@file_count.xml", 'w') {|f| f.write(xml) }
    filecount += 1
    offset += count
  end

有没有办法在没有 block 语法的情况下使用Builder?有没有办法以编程方式告诉它“关闭当前节”而不是依赖 block ?

最佳答案

我的建议:不要使用构建器。

只要正确转义 xml 实体,XML 就是一种简单的格式。

对数据库检索进行批处理,然后将批处理作为 xml 写入文件句柄。正如您的示例所示,不要通过字符串进行缓冲。只需写入文件句柄即可。让操作系统处理缓冲。文件可以是任意大小,为什么有限制?

另外,不要包括缩进空格,如果有百万行,它们就会加起来。

已添加 在编写 xml 文件时,我还在文件顶部包含 xml 注释:

  • 生成 xml 文件的软件名称和版本
  • 文件写入的日期/时间戳
  • 其他有用的信息。例如,在这种情况下,您可以说该文件是原始数据集的 # x 批处理。

关于 ruby /生成器 API : create XML without using blocks,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11193565/

相关文章:

ruby-on-rails - 从 pry 动切换到 IRB

ruby - 里程表上出现多少次零

.net - 是否有 Groovy 和 Grails 或 Ruby on Rails 的 .NET 等价物?

javascript - 如何使用 .get() 函数将从 XML 读取的值存储到本地对象的成员

Java 在特定类上改进 Builder 模式

mysql - 将 Upsert 与 MySQL2 和 Rails 4 一起使用时访问被拒绝

xml - 如何使用 name() 动态应用模板?

json - 通过 XSLT 将 XML 转换为 JSON

python - Python 中的 `Builder` 设计模式是否已过时?

c++ - 没有 unique_ptr 的现代 C++ 构建器模式