prawnto: render prawnto view for an email attachment

462 views
Skip to first unread message

Josh Coffman

unread,
Jan 10, 2010, 1:16:11 AM1/10/10
to prawn...@googlegroups.com
Hi,

  Is there a way to render a prawnto view to use as an email attachment?  Using prawn directly wasn't too hard to figure out, but my I'm not sure how to handle this in rails and my google-fu is failing me on this one.  

Here's how I attached a pdf using prawn directly:
    attachment :content_type => "application/pdf", 
      :filename => file_name do |a|
      a.body = Prawn::Document.new do
   text "hello world!"
 end.render
    end

Thanks,
-j

James Healy

unread,
Jan 10, 2010, 4:02:11 AM1/10/10
to prawn...@googlegroups.com
I have a similar requirement where reports have to be available via HTTP
and as an email attachment.

In the end I decided prawnto wasn't a good fit and just used raw prawn,
as described in this blog post[1]. That said, others may have found a
nice way to attach prawnto views to emails.

-- James Healy <ji...@deefa.com> Sun, 10 Jan 2010 19:58:18 +1100

[1] http://yob.id.au/2009/05/30/prawn-and-x-accel-redirect.html

> -- <br />
>
> You received this message because you are subscribed to the Google Groups "Prawn" group.<br />
>
> To post to this group, send email to prawn...@googlegroups.com.<br />
>
> To unsubscribe from this group, send email to prawn-ruby+...@googlegroups.com.<br />
>
> For more options, visit this group at http://groups.google.com/group/prawn-ruby?hl=en.<br />
>

Shmel

unread,
Jan 10, 2010, 5:49:48 PM1/10/10
to Prawn
One option, if you have implemented method (show for example) to
render pdf via HTTP, you can do
pdf_body = render_to_string(:action=>'show', :template=>'helloworld/
show.pdf.prawn')
and pass pdf_body to method in ActionMailer to be attached.

Shmel

Josh Coffman

unread,
Jan 11, 2010, 5:25:16 PM1/11/10
to prawn...@googlegroups.com
I got it working using a shared partial and render_to_string.  I put my shared partials in views/shared/...  In one controller where its used for a preview, it's just called normally using render :partial blah blah blah.  In another controller where I'm calling render_to_string(), I still have to setup the layout using the prawn view file in :action =>"..".  I pass that variable into my emailer which sets it as a pdf attachment.

I could show an example if anyone cares.  Since I'm not a ruby/rails expert, there is probably a better way to do it.

thanks,
-j



Josh C.
480-270-4578 | josh [at] computeristsolutions [dot] com | http://computeristsolutions.com


--

You received this message because you are subscribed to the Google Groups "Prawn" group.
To post to this group, send email to prawn...@googlegroups.com.
To unsubscribe from this group, send email to prawn-ruby+...@googlegroups.com.

pavling

unread,
Feb 10, 2010, 10:54:47 AM2/10/10
to Prawn
On Jan 10, 6:16 am, Josh Coffman <joshcoff...@gmail.com> wrote:
>   Is there a way to render a prawnto view to use as an email attachment?

I've spent the day today fiddling with this requirement for myself,
and thanks to this thread and a couple of others I have come to a
working solution.
I've posted to the thread at
http://www.workingwithrails.com/forums/4-ask-a-rails-expert/topics/804-send-dynamicly-generated-pdf-as-attachement
with my solution - no sense in cross-posting the same code in loads of
places.

HTH.

Gregory Brown

unread,
Feb 10, 2010, 11:10:42 AM2/10/10
to prawn...@googlegroups.com

It amazes me that people still don't understand that if you don't want
a large amount of code in your controllers, you create a module or
class, and call it from your controllers. As much as I think prawnto
is valuable for certain use cases, I blame it for bringing us so many
people who don't quite know what they're doing.

Our recommended process for using Prawn in Rails should make this a no-brainer:
http://wiki.github.com/sandal/prawn/using-prawn-in-rails

Gregory Brown

unread,
Feb 10, 2010, 11:17:34 AM2/10/10
to prawn...@googlegroups.com
On Wed, Feb 10, 2010 at 11:10 AM, Gregory Brown
<gregory...@gmail.com> wrote:
> On Wed, Feb 10, 2010 at 10:54 AM, pavling <pav...@gmail.com> wrote:
>> On Jan 10, 6:16 am, Josh Coffman <joshcoff...@gmail.com> wrote:
>>>   Is there a way to render a prawnto view to use as an email attachment?
>>
>> I've spent the day today fiddling with this requirement for myself,
>> and thanks to this thread and a couple of others I have come to a
>> working solution.
>> I've posted to the thread at
>> http://www.workingwithrails.com/forums/4-ask-a-rails-expert/topics/804-send-dynamicly-generated-pdf-as-attachement
>> with my solution - no sense in cross-posting the same code in loads of
>> places.
>
> It amazes me that people still don't understand that if you don't want
> a large amount of code in your controllers, you create a module or
> class, and call it from your controllers.   As much as I think prawnto
> is valuable for certain use cases, I blame it for bringing us so many
> people who don't quite know what they're doing.

BTW, Michael, the above is directed at that thread in general, not at
your post. But I still think that the code you posted:

av = ActionView::Base.new(Rails::Configuration.new.view_path)
av.extend ApplicationController.master_helper_module
av.controller = ActionController::Base.new
av.controller.request = ActionController::Request.new({
"SERVER_PROTOCOL" => "", "REQUEST_URI" => "",
"action_controller.request.request_parameters" => {:format => :pdf} })
av.controller.response = ActionController::Response.new
av.controller.headers = Rack::Utils::HeaderHash.new
av.controller.prawnto :prawn => { :page_size => 'A4' } # your
Prawto settings here....
pdf = Prawn::Document.new(av.controller.instance_variable_get(:@prawnto_options)[:prawn])
pdf_body = av.render(:file => 'reports/render_me.pdf.prawn', :locals
=> {:pdf => pdf}, :layout => false )
File.open("MGPtest", 'w') {|f| f.write(pdf_body) }

Is a *huge* price to pay to render PDF code you stuck in your views.
What are the upsides here?

-greg

Michael Pavling

unread,
Feb 10, 2010, 11:31:18 AM2/10/10
to prawn...@googlegroups.com
Gregory Brown <gregory...@gmail.com> wrote:
> BTW, Michael, the above is directed at that thread in general, not at
> your post.

Thanks for the clarification; I was just writing a slightly more snide
reply! ;-)

> Our recommended process for using Prawn in Rails should make this a no-brainer:
> http://wiki.github.com/sandal/prawn/using-prawn-in-rails

Using the recommended process is great (and I am, in its place), but
this topic is about how to render views *outside* of controllers.
Shock, horror! It's totally against the strict "way", but sometimes
you've just got to do what you need to. Whether it's right or wrong is
a separate debate; the question was how to do it...

The code I've posted allows people to hack the functionality of
rendering templates in models; in the example, I happen to be
rendering a Prawnto PDF, but I equally have rendered HTML/erb views.

> But I still think that the code you posted is a *huge* price to pay to render PDF code you stuck in your views.

I totally agree. It's horrid and smelly, and is deliberately breaking
the pattern to achieve its goal.

> What are the upsides here?

My specific use-case is that on the change of an AASM state, in some
cases, I need to automatically generate a PDF report (that already
exists as a controller view that can be run manually when a user wants
to) and email it off, while in the foreground, the current controller
action continues as normal. The state can be changed from a variety of
different places: when a user makes a choice; a time period has
expired; a parent record gets updated, and the model couldn't care
less where the call has come from - it only cares that the state has
changed and it needs to generate the report.

To stay DRY, I want to reuse the report code I already have as a
template, but I need to run it from a model, hence the hack-age.

If there's a nicer way, I'd love to use it, but a day of Googling
gleaned little more that a few people struggling to get as far as I
have, so I've posted my progress in the hope that it might be of use,
or be improved on by others.

Gregory Brown

unread,
Feb 10, 2010, 11:51:29 AM2/10/10
to prawn...@googlegroups.com
On Wed, Feb 10, 2010 at 11:31 AM, Michael Pavling <pav...@gmail.com> wrote:

> To stay DRY, I want to reuse the report code I already have as a
> template, but I need to run it from a model, hence the hack-age.
>
> If there's a nicer way, I'd love to use it, but a day of Googling
> gleaned little more that a few people struggling to get as far as I
> have, so I've posted my progress in the hope that it might be of use,
> or be improved on by others.

Read the recommended process. You put a class or module wherever you
want, and call it from wherever you need to.
I don't think Prawn cares whether you call SomeClassThatUsesPrawn from
within your models, views, or controllers, or wherever else.

To clarify, I am in no way suggesting you should inline Prawn code
into your controller. I'm suggesting you build a report object and
call it from wherever you need it.
Is there some use case that fails to account for?

-greg

Michael Pavling

unread,
Feb 10, 2010, 12:14:16 PM2/10/10
to prawn...@googlegroups.com
On 10 February 2010 16:51, Gregory Brown <gregory...@gmail.com> wrote:
> Read the recommended process.

I have; the first paragraph says "use Prawnto for something that looks
and feels a bit more Rails-ish" :-)

> To clarify, I am in no way suggesting you should inline Prawn code
> into your controller.

No, I didn't think that you were.

> Is there some use case that fails to account for?

Possibly the use-case that I already have loads of templates using
Prawnto features, and a new requirement to make one run in the
background outside of a controller. Having one report use one method,
while all the others use a different method wouldn't be ideal either.

In hindsight, maybe having not used the Rails-y feeling template
method would've been better - my first few PDFs were done using
send_data; gleaned from a PDF::Writer Railscast a few years ago. But I
switched to get lots of PDFs working quickly and easily. Now I find
myself backed into a corner, and have hacked my way out.

I can see my post was a little off topic for a Prawn-specific group,
but I thought it was worth posting an update to the thread that was
posing a similar problem to the one I faced this morning.

Gregory Brown

unread,
Feb 10, 2010, 12:26:06 PM2/10/10
to prawn...@googlegroups.com
On Wed, Feb 10, 2010 at 12:14 PM, Michael Pavling <pav...@gmail.com> wrote:
> On 10 February 2010 16:51, Gregory Brown <gregory...@gmail.com> wrote:
>> Read the recommended process.
>
> I have; the first paragraph says "use Prawnto for something that looks
> and feels a bit more Rails-ish" :-)

Yeah, I guess we should remove that line. We're trying to be positive
as much as we can here. Personally, I think Prawnto is probably
perfect for certain basic use cases. It's when things get more
interesting, that it falls down. I don't think it was ever meant to
serve those cases, though.

>> Is there some use case that fails to account for?
>
> Possibly the use-case that I already have loads of templates using
> Prawnto features, and a new requirement to make one run in the
> background outside of a controller. Having one report use one method,
> while all the others use a different method wouldn't be ideal either.

Hah, I see, and I agree. Technical debt is always an influencing
factor in situations like this.

> In hindsight, maybe having not used the Rails-y feeling template
> method would've been better - my first few PDFs were done using
> send_data; gleaned from a PDF::Writer Railscast a few years ago. But I
> switched to get lots of PDFs working quickly and easily. Now I find
> myself backed into a corner, and have hacked my way out.

I still don't get why ordinary object oriented design didn't save you
here. Is there some sort of special thing Prawnto is doing to make
reuse easier?
If you can show it to me, maybe I can give you and other users a sense
of how to do it without Prawnto. Or maybe I'll learn why people
bother to use Prawnto in the first place.

To this day, beyond making some magic happen with routing and avoiding
having to write your own render_pdf wrapper to call from your
controllers, I do not see what Prawnto does that vanilla Prawn lacks
in the context of Rails.

Honestly, I think that what we need is an extension that just gives
you those helpers and skips the magic views.

> I can see my post was a little off topic for a Prawn-specific group,
> but I thought it was worth posting an update to the thread that was
> posing a similar problem to the one I faced this morning.

Historically, we have encouraged Prawnto discussion, especially when
the maintainer (thorny_sun) was actively available to discuss these
details with users. But over time, as the core developers of Prawn
actually started using it in our Rails projects, we realized that we
didn't need Prawnto. It seems like that's the increasing trend among
everyday users as well.

Reply all
Reply to author
Forward
0 new messages