rails+prawnto: setting :type to :prawn in a #render_to_string call not working

Hello, my question is rails related though it is also somewhat specific to the prawnto plugin (installed latest version as of 2010-03-15). I would ask on a prawnto forum/list if I knew where one was.

Anyhow, I'm using rails 2.3.5 (with ruby 1.8.6 patchlevel 111) in an app that is successfully using the prawnto gem (with the prawn gem version 0.7.1). I've got a a WorksheetsController with the standard scaffold actions (and associated routes). I was able to drop in a "show.pdf.prawn" file into the associated view directory, write some prawn code in it, and add a "format.pdf { render :layout => false }" line inside the #show method's "respond_to" block. After doing this I could "view" my worksheets as PDF documents by adding a ".pdf" extension/type-definition to the end of the url:

http://localhost/worksheets/1.pdf

This is great. However, now I need to add a feature where someone can request that I email them a PDF copy of a worksheet. In the interest of being DRY, I want to re-use all the prawn pdf generation code in my "show.pdf.prawn" view file. After poking around, I figured #render_to_string might do the job.

The "email request" is implemented as the #email method/action in my controller. After grabbing the @worksheet object, I attempt to render the PDF as follows:

worksheet = render_to_string :action => "show", :layout => false, :type => :prawn

The #email action is always called via AJAX. Also, I have some AJAX stuff implemented for the #show action as show.rjs. The #render_to_string always renders the show action's RJS template, ignoring the :type => :prawn setting.

So, clearly I have a misunderstanding #render_to_string. I'm also wondering if there is a better way to accomplish what I need to do.

Any ideas?

So, if anyone is interested, I made a small, simple rails application that demonstrates what I'm trying to do (sort of), how I'm trying to do it, and how it fails. It has all gems it requires bundled. You just need ruby, rails 2.3.5, and sqlite3 to run it.

http://tinyurl.com/ygqvwt4

The real issue is that I can see no way to actually force or tell #render_to_string to render a "type" specified by me that differs from the requested "format".

The application has a worksheets controller/model/etc with only two extra, custom actions added: #print and #email. To get it to work, you'll need to define/replace the constants (tagged with TODO) acting as placeholders in the app/controllers/worksheets_controller.rb file.

In order to demonstrate that you CAN in fact use #render_to_string (if the underlying request's format/type is already of the desired type) to use prawnto to render a PDF to a string that you can then attach to a PDF, I duplicated some of the code in the #email method in the #print method. So, if you create a "worksheet" then "view" the worksheet and click the "print" link, it will render and display a PDF successfully as well as render a copy that will be sent to you as an email attachment.

However, if you try to accomplish this by clicking "Email" the #email method's identical code that calls #render_to_string will fail since the type/format isn't for a PDF (application/pdf or whatever). It instead fails as it wants to find an erb template (that doesn't exist).

So, what I'm really trying to do here isn't necessarily prawn/prawnto specific. I just want to be able to call #render_to_string in a controller to render an action (the same or another action) using a manually specified "type" (rjs, pdf, yourmom, whatever). Is there a way to do this and I'm just missing it? I've been reading the source and it appears the answer is I'll have to monkey-patch (doh).

Anyhow, if anyone also has any other good recommendations on how to keep controllers DRY when you need to do something like what I'm trying to do here, feel free to chime in.

I had a similar problem several weeks ago; I have lots of Prawnto views and I needed to render one outside of the ERB (to generate a PDF for an email file attachment).

In the end, I wrote some wholly ugly code to get around it: http://www.workingwithrails.com/forums/4-ask-a-rails-expert/topics/804-send-dynamicly-generated-pdf-as-attachement http://groups.google.com/group/prawn-ruby/browse_thread/thread/1859774668fc66a2

... my solution was certainly frowned on by the Prawn core; and they're correct. It does seem that Prawnto causes more problems than it solves by trying to be "nice". If you follow the Prawn guides for integrating with Rails, the process is a lot more re-useable.

But if you're in my position, and are stuck with loads of Prawnto views you can't get rid of overnight, then the solution I've posted will at least let you take their output and put it to different use.

Thanks for the reply. I ended up not needing to do what you did since I'm not needing to call #render_to_string from a model. However, the discussions and stuff you mentioned and included in your links gave me the answer that now works for my case. I was calling #render_to_string as follows:

document = render_to_string :action => "print", :layout => false

This didn't work because the print action had other, non prawnto templates in its template directory, specifically an RJS template. Since the action that contained the above line of code was always being called via AJAX and request.rjs? was always true, my request to render "print" as a string would always render my print.rjs template.

Reading your posted threads, I got the idea to try:

document = render_to_string :template => "worksheets/ print.pdf.prawn", :layout => false

This works perfectly for me and my simple case.

So, once again, thank!