I’m going to show you how to enable dynamic authoring of mail templates in your Rails app in Markdown. This includes Devise mailers. You can already customize templates with files in app/views, but we’ll take an extra step and expose an editable model in the database and allow our application administrators to author and edit templates in Markdown.
Template Model
Let’s add a MailTemplate that can render itself to HTML using Sanitize and RDiscount. The class name will be the mailer and the method name, the mail action.
We need to be able to render this in a mailer, so add a simple controller in app/controllers/mail_templates_controller.rb.
And a simple view, app/views/mail_templates/show.html.haml.
You can add a form to edit such a mail template, left as an exercise.
There’re a lot of mailers, so having to create each template by hand doesn’t make a lot of sense. There’s no easy way to enumerate all mailers, so lets define the in some central location and write a Rake task to create these in the database. I wrote app/mailers/mailers.rb.
It’s all pretty straightforward. You can add other mailers to Mailers.ALL. A rake task can invoke Mailers.create_templates! so that we get a record in the database with the default data. Here’s an example of app/views/devise/mailer/reset_password_instructions.md. Note that this is already written in markdown!
Hello <%=@resource.email%>!
Someone has requested a link to change your password, and you can do this through the link below.
[Change my password](https://example.com/users/password/edit?reset_password_token=<%=@resource.reset_password_token%>)
If you didn't request a password reset, please ignore this email.
Your password won't change until you access the link above and create a new one.
Overriding Devise
We want to override the Devise mailer and fetch the mail template, if available. Add app/mailers/devise_mailer.rb. The mailer will fetch a template from Mailers and render it.
Declare the mailer in config/initializers/devise.rb.
Tests
A simple test is to make sure we can actually render an e-mail. Here’s what my spec/mailers/devise_mailer_spec.rb looks like.
Next steps?
You tell me. I think we should be able to sink a lot of the functionality implemented in the Mailers module in various parts of the system. Starting with the .md rendering.