0

How I can setup controller/response objects from scratch to ran render_to_string?

I developed an application which generate a PDF file. I used erb based template to generate TeX file, then process it to convert to PDF.

It's working fine, but I now start thinking it is better to generate the report in background. Thus, I created a queuing system using delayed_job and it's working well.

Now, when combine two of them, I realized that renderer implemented as part of controller.

What I want to do is run render_to_string to generate the PDF. It looks like I need to setup controller and response object from scratch.

I found a question (How do I call controller/view methods from the console in Rails?) relate to this, but setting up a response object by calling post seems awkward.

How I can setup controller and response object to achieve this?

Community
  • 1
  • 1
shigeya
  • 4,862
  • 3
  • 32
  • 33

1 Answers1

1

Here's one way to do it (generating the PDF via wicked_pdf):

Controller:

class FoosController < ApplicationController

  def queue_pdf_generation
    @foo = Foo.find(params[:id])
    Delayed::Job.enqueue GeneratePdfJob.new(@foo.id)
  end

end

Delayed Job:

class GeneratePdfJob < Struct.new(:foo_id)

  def perform
    # get the Foo object when the job is run
    foo = Foo.find(foo_id)

    # create an instance of ActionView, so we can use render method outside of a controller
    av = ActionView::Base.new()
    av.view_paths = ActionController::Base.view_paths
    pdf_html = av.render :template => "foos/pdf.html.erb", :layout => nil, :locals => {:foo => foo}

    # use wicked_pdf gem to create PDF from the foo HTML
    foo_pdf = WickedPdf.new.pdf_from_string(pdf_html, :page_size => 'Letter')

    # save PDF to disk
    pdf_path = Rails.root.join('tmp', "#{foo.id}.pdf")
    File.open(pdf_path, 'wb') do |file|
      file << foo_pdf
    end

end

A couple notes:

  • The "perform" method doesn't take a parameter; inheriting from a struct lets us pass a parameter to the GeneratePdfJob object, and it sets up a local variable called "foo_id" that we can use in the "perform" method.
  • Your view needs to reference the local variable "foo" rather than an instance variable "@foo".
danblaker
  • 479
  • 4
  • 6