Action Mailer: How do I render dynamic data in an email body that is stored in the database?
I have Action Mailer setup to render an email using the body attribute of my Email model (in the database). I want to be able to use erb in the body but I can't figure out how to get it to render in the sent email message.
I'm able to get the body as a string with this code
# models/user_mailer.rb
def custom_email(user, email_id)
email = Email.find(email_id)
recipients user.email
from "Mail It Example <admin@foo.com>"
subject "Hello From Mail It"
sent_on Time.now
# pulls the email body and passes a string to the template views/user_mailer/customer_email.text.html.erb
body :msg => email.body
end
I came across this article http://rails-nutshell.labs.oreilly.com/ch05.html which says I can use render
but I'm only able to get render :text
to work and not render :inline
# m开发者_如何学JAVAodels/user_mailer.rb
def custom_email(user, email_id)
email = Email.find(email_id)
recipients user.email
from "Mail It Example <admin@foo.com>"
subject "Hello From Mail It"
sent_on Time.now
# body :msg => email.body
body :msg => (render :text => "Thanks for your order") # renders text and passes as a variable to the template
# body :msg => (render :inline => "We shipped <%= Time.now %>") # throws a NoMethodError
end
Update: Someone recommended using initialize_template_class
on this thread http://www.ruby-forum.com/topic/67820. I now have this for body
body :msg => initialize_template_class(:user => user).render(:inline => email.body)
It works but I don't understand this so I tried researching the private method and there is not much out there on it which makes me worry this is a hack and there is probably a better way. Suggestions?
Even if you end up unable to use render :inline, you can always instantiate ERb yourself.
require 'erb'
x = 42
template = ERB.new <<-EOF
The value of x is: <%= x %>
EOF
puts template.result(binding)
#binding here is Kernel::binding, the current variable binding, of which x is a part.
In rails 3.2 :inline method of render works just fine.
mail(:to => "someemail@address.com",
:subject => "test") do |format|
format.text { render :inline => text_erb_content }
format.html { render :inline => html_erb_content }
end
Tim's suggestion is on the right path. Here is how you implement ERB in the email action
def custom_email(user, email_id)
email = Email.find(email_id)
# more email setup ...
body :msg => ERB.new(email.body).result(binding)
# or ...
# body :msg => ERB.new(email.body).result(user.send(:binding))
end
The difference between the two hashes will determine what erb you user in the body attribute in the database table. With the first you have to use <%= user.name %>
to access your use. With the second you can just do <%= name %>
精彩评论