Skip to content

Instantly share code, notes, and snippets.

@ilake
Created May 28, 2014 05:59
Show Gist options
  • Save ilake/2503b32534e946d05019 to your computer and use it in GitHub Desktop.
Save ilake/2503b32534e946d05019 to your computer and use it in GitHub Desktop.

There is a library in isis. This is convenient to generate pdf out of controller, becasue we have a view object and I hope the pdf generation is binding to it.

# lib/princely_pdf.rb
module PrincelyPdf
  extend ActiveSupport::Concern

  included do
    include ActionController::Rendering
    include Princely::PdfHelper
    include Princely::AssetSupport
  end

  def build_pdf_data(options = {})
    options = {
      :stylesheets => [],
      :layout => false,
      :relative_paths => true,
      :server_flag => true
    }.merge(options)

    prince = Princely::Pdf.new(options.slice(:server_flag))
    # Sets style sheets on PDF renderer
    prince.add_style_sheets(*options[:stylesheets].collect{|style| asset_file_path(style)})

    html_string = render_to_string(options.slice(:template, :layout, :handlers, :formats))

    html_string = localize_html_string(html_string, Rails.public_path) if options[:relative_paths]

    prince.pdf_from_string(html_string)
  end

  def pdf_file(options = {})
    @pdf_file ||= begin
                    options[:pdf_file_data] ||= build_pdf_data(options).force_encoding('utf-8')
                    options[:filename] ||= "report"

                    report_temp_file = Tempfile.new([ options[:filename], '.pdf' ])
                    report_temp_file.write(options[:pdf_file_data])
                    report_temp_file.rewind
                    report_temp_file
                  end
  end

  def render_to_string(options = {})
    raise 'overwrite me'
  end
end
# view object
require 'princely_pdf'

class StudentTranscript
  include PrincelyPdf
  
  def render_to_string(options = {})
    av = ActionView::Base.new(ActionController::Base.view_paths)
    av.extend TranslationHelper
    av.render(:template => "contacts/transcripts/index.pdf.erb",
              :layout => options[:layout],
              :locals => {
                          :@school => SchoolDecorator.new(school),
                          :@student => StudentProfilePresenter.new(student)
                         })
  end
end

But I feel bad smell here, because we just use the template in this view object, that is fine. But if we need this template both from view object and controller, that may violate the DRY policy, I feed that will be danguerous, because you probably forget to add some variables in other place, Anyone have better idea ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment