Rails: Custom template for email "deliver_" method?
I'm building an email system that stores my different emails in the database and calls the appropriate "deliver_" method via method_missing
(since I can't explicitly declare methods since they're user-generated).
My problem is that my rails app still tries to render the template for whatever the generated email is, though those templates don't exist. I want to force all emails to use the same template (views/test_email.html.haml
), which will be setup to draw their formatting from my database records.
How can I accomplish this? I tried adding render :template => 'test_email'
in the test_email
meth开发者_如何学编程od in emailer_controller
with no luck.
models/emailer.rb
:
class Emailer < ActionMailer::Base
def method_missing(method, *args)
# not been implemented yet
logger.info "method missing was called!!"
end
end
controller/emailer_controller.rb
:
class EmailerController < ApplicationController
def test_email
@email = Email.find(params[:id])
Emailer.send("deliver_#{@email.name}")
end
end
views/emails/index.html.haml
:
%h1 Listing emails
%table{ :cellspacing => 0 }
%tr
%th Name
%th Subject
- @emails.each do |email|
%tr
%td=h email.name
%td=h email.subject
%td= link_to 'Show', email
%td= link_to 'Edit', edit_email_path(email)
%td= link_to 'Send Test Message', :controller => 'emailer', :action => 'test_email', :params => { :id => email.id }
%td= link_to 'Destroy', email, :confirm => 'Are you sure?', :method => :delete
%p= link_to 'New email', new_email_path
Error I'm getting with the above:
Template is missing
Missing template emailer/name_of_email_in_database.erb in view path app/views
Try multipart may that work
def test_email
@email = Email.find(params[:id])
Emailer.send("deliver_#{@email.name}")
part :content_type => 'multipart/alternative' do |copy|
copy.part :content_type => 'text/plain' do |plain|
plain.body = render( :file => "conta.text.plain.erb", :email=>@email )
end
copy.part :content_type => 'text/html' do |html|
html.body = render( :file => "conta.text.html.erb", :email => @email )
end
end
end
Aph, I feel silly. I figured it out:
models/emailer.rb
:
class Emailer < ActionMailer::Base
def method_missing(method, *args)
logger.info "method missing was called!!"
recipients "Test <test@test.com>"
body "#{ Email.find_by_name(method.to_s).body }"
end
end
Since the incoming method
is basically the name of the record, I can pull the body content stored in the database directly and pass that in as the body of the email, bypassing the templates altogether.
I'd go "up a level"
In other words, use the same view for everyone's email. But in the view, render different text depending on the user_id.
Remember that the view can call the render method.
In my case, I let users upload email templates using the liquid template system. (Google for rails liquid templates.) Using liquid is good since it is safe--users can't include arbitrary ruby code in their templates.
Then my email view renders the liquid template and the customized email is thereby generated.
精彩评论