Forum: Ruby on Rails rails+prawnto: setting :type to :prawn in a #render_to_string call not working

94cee02d73877ef5e6dfb04afb1fe324?d=identicon&s=25 Kendall Gifford (zettabyte)
on 2010-03-17 19:17
(Received via mailing list)
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?
94cee02d73877ef5e6dfb04afb1fe324?d=identicon&s=25 Kendall Gifford (zettabyte)
on 2010-03-18 00:06
(Received via mailing list)
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.
56b7e1808013614acdb73cbaaa6938a1?d=identicon&s=25 Michael Pavling (Guest)
on 2010-03-18 10:06
(Received via mailing list)
On 17 March 2010 23:05, Kendall Gifford <zettabyte@gmail.com> wrote:
> 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-rai...
http://groups.google.com/group/prawn-ruby/browse_t...

... 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.
94cee02d73877ef5e6dfb04afb1fe324?d=identicon&s=25 Kendall Gifford (zettabyte)
on 2010-03-18 17:28
(Received via mailing list)
On Mar 18, 3:04 am, Michael Pavling <pavl...@gmail.com> wrote:
> 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!
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.