Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #2926 (reopened defect)

Opened 3 years ago

Last modified 1 year ago

[PATCH] render :partial from within a mail template doesn't work

Reported by: jeroen@supercool.nl Assigned to: jamis@37signals.com
Priority: high Milestone: 2.x
Component: ActionMailer Version: 1.2.2
Severity: major Keywords: render :partial mail email
Cc: bitsweat, japgolly@gmail.com, mmoen, someone23

Description

This happens in a view that's being used to create an email:

undefined method `controller_path' for SupportMailer:Class

Extracted source (around line #8):

5: 6: <%= @url %> 7: 8: <%= render_partial 'sig_admin' %>

Attachments

action_mailer_render_partial.patch (2.5 kB) - added by mmoen on 09/15/06 06:45:49.
Patch for ActionMailer render partials (including templates this time, sorry)
support_shared_partials_in_actionmailer.diff (1.9 kB) - added by sublogical on 07/23/07 20:58:40.
Support for passing relative paths to partials like in Rails

Change History

11/18/05 06:05:40 changed by bitsweat

  • cc set to bitsweat.
  • milestone set to 1.1.

Does render :partial => 'sig_admin' work?

03/16/06 17:27:25 changed by larimer@fantasybowl.com

I'm not the original bug reporter, but I am having the same problem.

No... "render :partial => 'template_name'" produces the same error.

03/21/06 13:23:13 changed by japgolly@gmail.com

  • cc changed from bitsweat to bitsweat, japgolly@gmail.com.
  • version changed from 0.14.3 to 1.0.0.
  • severity changed from normal to blocker.

It fails because ActionMailer doesn't contain a controller_path class method.

I thought i'd just simply create it but it's not as simple as that. I had two mailers, StudentMailer and TeacherMailer. I added class methods to both that return 'student_mailer' and 'teacher_mailer' respectively. This failed because the current directory of the template class is already in those directories. So I changed them both to return '.'

This appeared to work fine. I had two seperate partial templates, both called "booking", one for each mailer, both in their respective view directories. When I sent mails from both mailers in the same action, they would use the wrong template sometimes. ie. the StudentMailer would use teacher_mailer/_booking.rhtml. I even changed the controller path functions to return '../student_mailer' and '../teacher_mailer' respectively but it still wouldn't work. Odd problem.

03/22/06 22:27:24 changed by railsav.9.sts@xoxy.net

The wrong template can be used because both booking templates get compiled into the same method name in ActionView. I think you need to use different names for these templates until this is fixed.

03/23/06 02:44:47 changed by anonymous

  • keywords changed from render :partial mail email to render :partial mail email needs_review.

03/24/06 15:21:52 changed by shanti@sproutit.com

Jonathan Viney posted a workaround for this on the mailing list:

I've got this piece of code in an AM template: <%= render :partial => '../shared/listing' %> I think the default path is the current path of the AM template, so ../ puts it down into app/views/. That line will render app/views/shared/_listing.rhtml.

http://www.ruby-forum.com/topic/59024

This works for me on edge Rails rev. 4014.

03/25/06 23:33:28 changed by david

  • owner changed from David to jamis@37signals.com.

03/25/06 23:33:44 changed by david

  • severity changed from blocker to normal.

03/26/06 03:37:03 changed by david

  • keywords changed from render :partial mail email needs_review to render :partial mail email.

04/04/06 21:13:03 changed by Newhydra

  • severity changed from normal to major.

Jonathan Viney posted a workaround for this on the mailing list: > I've got this piece of code in an AM template: > > <%= render :partial => '../shared/listing' %> > > I think the default path is the current path of the AM template, so > ../ puts it down into app/views/. That line will render > app/views/shared/_listing.rhtml. >

http://www.ruby-forum.com/topic/59024

This works for me on edge Rails rev. 4014.


This appears to work, however, there is a problem with it: Let's say you have a partial (call it 'foo') which lives in your 'bar' views. Then let's say that the 'foo' partial renders a partial called 'part' which lives in the 'tial' views.

Now, if you want to render the 'foo' partial from both your normal application and an actionmailer instance, you run into problems.

It's easy enough to render the 'foo' partial, however, the problem comes in when you need to render the 'part' partial.

If you use render :partial=>'../tial/part' then your application can't render it. If you use render :partial=>'tial/part' then your actionmailer view can't render it.

04/05/06 16:41:02 changed by Newhydra

A temporary workaround is to send a partial_prefix string to the partial, and then modify the render :partial call to this: render :partial=>"#{@partial_prefix}tial/part"

In your actionmailer you need to set :partial_prefix => "../" in body.

04/10/06 06:03:05 changed by japgolly@gmail.com

  • milestone changed from 1.1 to 1.2.

FYI: With 1.1.2 just being released and lots of internal changes having been made to ActionView over the past month or so, I was curious if this would now magically work, give a different error or just give the same error as before. Unfortunately even with 1.1.2 it just gives the same error. Just FYI.

07/13/06 08:56:51 changed by anonymous

  • priority changed from normal to high.

yeah, this sucks. please fix it!

09/15/06 06:34:02 changed by mmoen

  • cc changed from bitsweat, japgolly@gmail.com to bitsweat, japgolly@gmail.com, mmoen.
  • version changed from 1.0.0 to edge.
  • summary changed from render :partial from within a mail template doesn't work to [PATCH] render :partial from within a mail template doesn't work.

This appears to fix the render :partial problem in ActionMailer templates.

I also did a local test case that attempts to replicate japgolly@gmail.com's problem of pulling the wrong partials when calling different ActionMailer classes from the same controller action and it appears to work as expected. That test app can be found here action_mailer_partials.tgz (49k)

09/15/06 06:45:49 changed by mmoen

  • attachment action_mailer_render_partial.patch added.

Patch for ActionMailer render partials (including templates this time, sorry)

11/05/06 02:32:41 changed by bitsweat

  • milestone changed from 1.2 to 1.x.

This looks like a reasonable workaround. Jamis?

02/21/07 12:49:28 changed by josh

  • status changed from new to closed.
  • resolution set to fixed.

Running the patch actionmailer/test/mail_render_test.rb file, all the unit test passed. This was on Rails 1.2.2. I'm thinking its fixed. I'll go ahead and close the ticket since its relatively old. If its still broken feel free to reopen it again.

07/10/07 00:05:07 changed by someone23

  • status changed from closed to reopened.
  • version changed from edge to 1.2.2.
  • resolution deleted.

I'm having a very similar problem to this which the patch doesn't appear to fix. I applied it an the tests passed, but I still can't render a shared partial from the mailer view. Perhaps this is a separate issue, but it seems to me like a continuation of this issue to me.

When I try a

<%= render :partial => "shared/my_partial" %>

in a mailer view without the patch it can't find the partial because it's looking in app/view/my_notify. If I try it with adding a "../" to that partial path then it complains about finding other partials that I render from that partial. I get the same behavior in both cases if I don't have the patch applied.

07/10/07 00:06:49 changed by someone23

  • cc changed from bitsweat, japgolly@gmail.com, mmoen to bitsweat, japgolly@gmail.com, mmoen, someone23.

07/23/07 20:58:40 changed by sublogical

  • attachment support_shared_partials_in_actionmailer.diff added.

Support for passing relative paths to partials like in Rails

07/23/07 21:00:32 changed by sublogical

I've run into this as well. The problem appears to be that ActionMailer sets the ActionView base path to be the entire path into the mailer's view directory, ex:

src/my_rails_app/app/views/my_mailer

Then when we render the email, it just passes the name of the method, say "foo", so ActionView looks for, ex:

src/my_rails_app/app/views/my_mailer/foo

This is different than rails, which sets the base path to the view directory, ex:

src/my_rails_app/app/views

And passes the subdirectory in the call to render, say "my_mailer/foo".

I've attached a patch that sets the ActionView base to the view directory and passes through the subdirectory in the render call. This allows me to correctly use shared partials. See support_shared_partials_in_actionmailer.diff.

-jay