Reputation: 1397
Our Rails (3.0.14) application has user profiles where users can choose whether they want to receive HTML formatted emails. To keep things DRY, I would like to only setup one set of templates for all mails (HTML) and then use my own String extension dehtml
(basically strip_tags
with some formatting modifications) on the text/plain part. Also, I would like to keep the mailer code DRY.
So far, our mailer methods look like this:
def signup_confirmation(user)
@user = user
mail(:to => @user.email, :subject => ..., ...)
end
1. DRY templates: If possible, I would like to avoid having to create 200 additional mail templates, and autocreate the text/plain part from the HTML template. This is the basic idea (dehtml
is my own String extension):
def signup_confirmation(user)
@user = user
mail(:to => @user.email, :subject => ..., ...) do |format|
format.html
format.text { render(:file => 'signup_notification.html').dehtml }
end
end
However, this fails with a 'missing template' error. How do I tell Rails to use the HTML template in both cases? I tried appending :formats => :html
and :handler => :html
but this didn't help.
I don't have a solution here right now. Any ideas?
2: DRY mailer methods: Since our users should be able to decide whether they want to have HTML or not, the above method will look something like
def signup_confirmation(user)
@user = user
attachments.inline["email-header.jpg"] = File.read(...) if @user.wants_html
mail(:to => @user.email, :subject => ..., ...) do |format|
format.html if @user.wants_html
format.text { render(:file => 'signup_notification.html').dehtml }
end
end
Altogether, this triples the LOC in each method. I would like to DRY this up (since it will have to be inserted into at least 200 mailer methods) as far as possible. One idea would be to write my own mail
method (let's call it mymail
) as something like
def mymail(user, p={})
attachments.inline["email-header.jpg"] = File.read(...) if user.wants_html
mail(p) do |format|
format.html if user.wants_html
format.text
end
end
(ignoring the above text template problem for now) and then change each call to mail
to mymail
, as in
def signup_confirmation(user)
@user = user
attachments.inline["email-header.jpg"] = File.read(...) if @user.wants_html
mymail(user, { :to => @user.email, :subject => ..., ... })
end
This works. But is it good practice? Where do I best put mymail
- in a helper?
Any insights and recommendations welcome!
Upvotes: 1
Views: 526
Reputation: 3965
I did something very similar to your first solution a long time ago. I don't really remember why it hat to be the way it is, but this is working for me:
def my_mail
mail(:to => @user.email ...) do |format|
format.text { convert_html_to_plain(__method__) } # first text
format.html # then html
end
end
def convert_html_to_plain(method)
old_formats = self.formats
self.formats = ["html"]
rendered = render "#{method}", :layout => false
self.formats = old_formats
# strip tags, reformat, etc. from rendered
rendered << render(:partial => "plaintext_footer", :locals => {:user => @user}, :formats => [:text] )
end
Upvotes: 1