Scenario: You have a string variable populated with an ERb template which you want to use in ActionMailer, rather than using the default method-named file-based template.
Solution: ActionView to the rescue! Add a method similar to the following to your ActionMailer model:
def email_from_template(to,from,subject,template_string,assigns={})
email_builder = ActionView::Base.new
recipients to
from from
subject subject
part "text/html" do |a|
a.body = email_builder.render(
:inline => template_string,
:locals => assigns
)
end
end
Now from anywhere in your application, you can call:
Mailer.deliver_email_from_template(
'<a href="mailto:user@isp.com">user@isp.com</a>',
'<a href="mailto:admin@myapp.com">admin@myapp.com</a>',
'Email Alert',
some_big_long_erb_string,
{ :foo => @foo, :another => @cool_object }
)
Note that there appears to be a bug in the Wiki. The above email addresses should simply be the email addresses themselves and not enclosed in HTML anchor tags.
Enjoy!
— solo
I couldn’t get the above to pass varibles to the template. However, the following minor modifications (moving assings from the render call to the ActionView::Base.new call) worked for me.
email_builder = ActionView::Base.new(nil,assigns)
a.body = email_builder.render(
:inline => template_string,
}
I am writing an mail sender that is fed with templates by the user and then substitutes some values in the templates. It could handle both erb and plain text templates.
For example
"<h1>A good morning wish
Good morning, <= @name>"
"hello,#{@name}"
require "erb"
class String
def substitute(binding=TOPLEVEL_BINDING)
eval(%{"#{self}"}, binding)
end
end
#substitutes the values in a given string or erb template with the ones given in
#args. Currently there are two valid values for type: “ruby” and “rhtml”.
class ArgumentSubstituter
def self.substitute args,template,type
args.each do |k,v|
## create and initialize an instance variable for this key/value pair
self.instance_variable_set(“@#{k}”, v)
end
if type == “ruby”
template.substitute(binding)
elsif type == “rhtml”
e = ERB.new template
e.result(binding)
end
end
end
Now here is how the template defined at run-time. I have a mailer called GoodMorningMailer and in it I have a method called send. send.rhtml is simple – it contains only @body as text. I fill @body using the above described class in my send method and everything seems ok.
—Izomorphius