Search code examples
ruby-on-railsrubypdfrenderinghtmldoc

PDF export from a Model method using render_to_string


I need to implement a _to_pdf method on my ProjectBill model which generates a PDF of my bill at this place:

/public/xls/bills/project_#{project.number}_bill_#{bill.number}.pdf

My application is using HTMLDoc for generating PDF. I am using Rails 2.3.11. With the HTMLDoc gem, I need to pass a render_to_string of my partial view _bill.pdf.haml, wich is not accessible in the model (only in the controllers), to HTMLDoc.

I already have an export_to_pdf action in my controller, triggered by the user when he wants an export (this one works). The model method will be called by a scheduled task, an emailer sending the bills when the scheduled_date is equal to Date.today.

I've already tried tons of solutions:

  • http://www.omninerd.com/articles/render_to_string_in_Rails_Models_or_Rake_Tasks/print_friendly
  • Have a to_pdf action on my ProjectBill controller and call it in from Model (but not working, saying that render_to_string is not defined even if its called in the Controller)
  • Use my working export_to_pdf method with a get request sent from my Model (but I figured out that I cannot really send a request from a Model...)
  • Use a Helper with the render_to_string inside it (not working: undefined method)
  • and even more !

But still not working.

Can somebody help me with this issue? Im stuck and can't find any solution...


Solution

  • Ahh I finally did it !

    Thanks for your answer Sean but I was not looking for a better Gem, I was looking for a solution to my issue.

    For some reason I couldn't use the render_to_string method in my Model... So I created my export_to_pdf method on my model:

      def export_to_pdf
        bill = self
        project = self.project
    
        path = "facture_#{self.project.id}_#{self.bill_number}_#{Date.today.strftime('%Y_%m_%d')}.pdf"
    
        Plus::BillingItemsController.new._to_pdf(bill.id)
    
        if File.exists?(path)
          return path
        else
          return nil
        end
      end
    

    As you can see I call my Controller in my Model. Here is my _to_pdf method:

     def _to_pdf(bill_id)
        @bill = Plus::ProjectBill.find_by_id(bill_id)
        @project = @bill.project
        path = "#{RAILS_ROOT}/public/xls/facture_#{@project.id}_#{@bill.bill_number}_#{Date.today.strftime('%Y_%m_%d')}.pdf"
    
        av = ActionView::Base.new(Rails::Configuration.new.view_path)
        av.class_eval do
          include ApplicationHelper
          include ActionController::UrlWriter
          default_url_options[:host] = 'mysite.com'
        end
    
        av.extend ApplicationController.master_helper_module
        html = av.render(:partial => "/plus/billing_items/bill_for_pdf.haml", :locals => {:bill => @bill})
        data = to_pdf(html, false, {:header => '', :headfootsize => 0, :outfile => path})
      end
    

    My to_pdf function is just doing the PDF::HTMLDoc.new and the set_option of links, logoimage , etc. and return pdf.generate

    I hope this can help someone someday somewhere !