Ruby: Prawn PDF out of memory when using the group method

妖精的绣舞 提交于 2019-12-23 18:05:24

问题


I have a large number of products I want to display in a pdf, with category headers. If a category doesn't fit on the current page I want to move it to the next. For this I'm using Prawn's group method.

Product.all.group_by(&:category).each do |category, products|
  pdf.group do
    # Simplified the data a bit for this example
    pdf.text category
    pdf.table products.map{ |p| [p.title, p.price] }
  end
end

This works very well for small amounts of products, but when I add more than 100 or so it takes a very long time and then ends in "failed to allocate memory". If I don't use the group method it takes about 30 seconds.

Clearly the group method does not manage its memory usage very well. Any suggestions for workarounds would be appreciated.


回答1:


---------- UPDATED ANSWER --------

The previous workaround wasn't good enough for the production server, so I had to use development version from git repo installed as a submodule under vendor/prawn, as described here: https://github.com/sandal/prawn/wiki/Using-Prawn-in-Rails

The memory issue with the group method is gone, but the syntax/options for things have changed somewhat. So I had to rewrite the code to generate PDF.

Also, getting the submodule to play nicely with the git repo for the Rails app is difficult. Deployment to production was tough.

---------- ORIGINAL ANSWER --------

This isn't a fix, but it makes the problem take a few more group iterations before it manifests itself:

  • override the Prawn::Document instance method named 'group'
  • use the code from the 'group' function from the newest development version of prawn (from github.com)

The way I did this is that I added a file to the /lib folder of my Rails app. This file will include the Prawn gems and defined the mime type for a PDF document:

class PdfPrawn
  require 'prawn'
  require 'prawn/core'
  require 'prawn/table'
  MIME_TYPE = "application/pdf"
end
class Prawn::Document
  def group(second_attempt=false)
    old_bounding_box = @bounding_box
    @bounding_box = SimpleDelegator.new(@bounding_box)

    def @bounding_box.move_past_bottom
      raise RollbackTransaction
    end

    success = transaction { yield }

    @bounding_box = old_bounding_box

    unless success
      raise Prawn::Errors::CannotGroup if second_attempt
      old_bounding_box.move_past_bottom
      group(second_attempt=true) { yield }
    end

    success
  end
end

And then in a model file, I define a method to generate my PDF and use something like this:

def to_pdf
  require "#{File.expand_path(RAILS_ROOT)}/lib/pdf_prawn"
  pdf = Prawn::Document.new
  # code to add stuff to PDF
  pdf.render
end



回答2:


I was using prawn on one project, sorry to tell that, but it was an disaster, finally we had to switch to wicked pdf. I advice you to do the same before you do not have to much code.



来源:https://stackoverflow.com/questions/4210251/ruby-prawn-pdf-out-of-memory-when-using-the-group-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!