Welcome to Working With Rails


Discussion Forums

Discuss all things Ruby on Rails with perhaps the web's most vibrant group of Ruby on Rails enthusiasts.
Send dynamicly generated pdf as attachement
11 Posts
Send dynamicly generated pdf as attachement


I've got a form and I'd like to send the value of that form as an attachement (pdf) to me. The generation of that pdf works fine (with prawn), thanks to the railscast, but could someone tell me how I could put that file as an attachement in my mail?

I'd like to only make it possible that only the send action could access/generate that pdf. How could I do this?

Refer to Rails API of ActionMailer::Base about sending mails with attachments. According to the document that you could just pass the content of generated PDF as params of the mailer class, looks like this:

def generated_pdf(recipient, pdf)
  attachment "application/pdf" { |a| a.body = pdf }

FYI, to get the content of generated PDF, the "render_as_string" method and read the response.body after rendering automatically will be both useful in this situation.

And how can I then generate the pdf document? Like the railscast, I just had to create a .pdf.prawn document and that's it.

You can move the logic that creates the pdf from the .prawn file to your controller or even better to a model. You will want to use pdf = Prawn::Document.new and the render method to create a string version of the pdf which can be attached to the email.

Check out http://prawn.majesticseacreature.com/docs/prawn-core/classes/Prawn/Document.html#M000097 and http://prawn.majesticseacreature.com/docs/prawn-core/classes/Prawn/Document.html#M000101.

You do not need the real PDF file as attachment. Actually, only the generated content (binary stream) of this pdf document is necessary. You can access to this stream via response object. Your codes of controller should looks like the following:

def show # just a example
  render # force to generate pdf using prawnto so we can access to the response object
  pdf = response.body
  YourMailer.deliver_generated_pdf(current_user, pdf)

I'm sorry for my late response, I had some last exams.

On topic :

I've tried to generate a pdf in my controller (that didn't go so fine), but recently I found this site (http://dizzy.co.uk/ruby_on_rails/cheatsheets/action-mailer#multipart_messages), and I quote

ActionMailer will automatically detect and use multipart templates, where each template is named after the name of the method, followed by the content type. Each such detected template will be added as a separate part to the message. For example:

signup_notification.text.plain.erb signup_notification.text.html.erb signup_notification.text.xml.builder

Each would be rendered and added as a separate part to the message with the corresponding content type. The same body hash is passed to each template.

So in my notifier view folder I created a send_mail.html.erb template and a send_mail.pdf.prawn, but when I send the email, the pdf attachement isn't added.

Could anyone tell me if this info is correct and what I'm doing wrong? http://pastie.org/551464

Hi Wouter,

How about this?

In your controller, you generate the PDF file:

Prawn::Document.new do      
    text "THIS IS A PDF"

Notifier.deliver_signup_notification(customer_email, pdf_file)

In your notifier action mailer:

def signup_notification(customer_email, pdf_file)
    @from         = "example@email.com"
    @recipients   = customer_email
    @subject      = "Reactie"
    @sent_on      = Time.now
    @content_type = "text/html"

    attachment :content_type => "application/octet-stream", :filename => "your_file_name_here.pdf", :body => pdf_file    

Hope that helps. Something wrong with format here, so I paste the code in "here":http://pastie.org/554806


Thanks Sonny, that's working fine but the problem is that I have 200 and more lines of code for generating the pdf and I'd like to keep it out of my controller so that it can stay clean. Isn't there a way to render some kind of template ( a .pdf.prawn) and include that in my Notifier.deliver methode?


Have you ever managed to get this working? I'm attempting to do the same thing. Basically what I want to do is have my model access the prawn pdf so I can easily attach the file when I send the email out. I found that you do it from the controller using: @output = render_to_string :template => 'invoices/show.pdf.prawn', :layout => false

But apparently you can't use render_to_string in the model or in a rake task. For a model and rake task I found these articles http://www.compulsivoco.com/2008/10/rendering-rails-partials-in-a-model-or-background-task/ http://www.gregorydoran.co.uk/2009/08/ruby-on-rails-rendering-views-outside-of-the-controller/ http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/14f5f3f6f7819d27

following those I figured in my Invoice Model I could do something like this

def pdf_file

av = ActionView::Base.new(Rails::Configuration.new.view_path)
av.extend ApplicationController.master_helper_module 
output = av.render(
  :file => 'invoices/show.pdf.prawn',
  :locals => {:invoice => self},
  :layout => false 


My ideas was in my mailer I could attach the file using something like this.

def test(user, invoice)

recipients    user.email
from          "Testing "
subject       "Email Testing"
body          :user => user
content_type "text/html"
attachment "application/pdf" do |a|
  a.body = invoice.pdf_file


But in the end I'm stuck with a weird prawn error

ActionView::TemplateError: ActionView::TemplateError (You have a nil object when you didn't expect it! The error occurred while evaluating nil.compute_prawnto_options) on line #1 of app/views/invoices/show.pdf.prawn: 1: pdf.text "Invoice ##{@invoice.id}", :size => 30, :style => :bold 2: pdf.text "#{@invoice.user.firstname} #{@invoice.user.lastname}", :size => 20 3: pdf.text "#{@invoice.user.address1}", :size => 20 ......

I know I'm not offering any solution but maybe some of this might point you into the right direction. Let me know if you ever get it working.


I didn't manage to fix this problem, I keep sending the mails in plain text rather than in pdf.

11 Posts
Login to add your message