We’ve been successfully using Roadie 2 to style our apps emails in the past, but we found out we needed to switch to v3 of the gem if we wanted it to work with Rails 4.2. Here’s a ‘how to’…
A couple of years ago, I wrote a small guide on how to use Roadie 2.3 to style emails in Rails applications. Time passed and since then, Rails 4.2 was released; last Sunday we just got Rails 5. While working on a new project using Rails 4.2, we found that Roadie 2 wasn’t working, so we needed to finally make the move and upgrade to Roadie 3.
This post covers the upgrading process, so refer to the post linked above for an explanation on why use to Roadie and how it works.
Installation
Roadie 3 is compatible with other Ruby based engines or frameworks, not just Rails. To get it working on Rails, you’ll need the Rails wrapper, aptly named roadie-rails.
To install it, you’ll just have to add gem 'roadie-rails', '~> 1.0'
to your Gemfile (and remove the old version, if you were using it!).
Configuration
Roadie 3 has two modes of working: Automatic
and Manual
. Automatic will take care of almost everything for you. To get this set up, we’ll need to include Roadie::Rails::Automatic
on our mailers:
class UserMailer < ActionMailer::Base
include Roadie::Rails::Automatic
# ...
If you are using several mailers with inline styling, you might want to extract the include sentence, and the declaration of layouts and helpers into an ApplicationMailer
that inherits from ActionMailer::Base
, then make all your mailers inherit from it.
In case you’re using Devise and you want your Devise mails sytled, you’ll need to add that, as well. You can do so by going to your application.rb
and adding:
#...
config.to_prepare do
Devise::Mailer.send(:include, Roadie::Rails::Automatic)
#...
Your email previewers shouldn’t need to be changed or updated. So, unless you want to dive into the manual mode – and you have your CSS and layout for emails (and plain-text parts) already in place – you’re all set.
Getting responsive templates in place
With Roadie 2, we were using HTML Email Boiler Plate to get a basic layout and CSS reset for our styled emails. However, we found the Responsive transactional HTML email templates created by Mailgun and they looked well documented, tested and supported, so we decided to give them a go.
This is the CSS reset and base file, and here are the HTML templates, which you can get an adapt for freely. Here’s a common one we use (in HAML, for commodity):
# app/views/layouts/email.html.haml
!!!
%html{xmlns: "http://www.w3.org/1999/xhtml"}
%head
%meta{content: "width=device-width", name: "viewport"}/
%meta{content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
%title= page_title
= stylesheet_link_tag :email, media: "all"
%body{itemscope: "", itemtype: "http://schema.org/EmailMessage"}
%table.body-wrap
%tr
%td
-# left blank deliberately
%td.container{width: "600"}
.content
%table.main{cellpadding: "0", cellspacing: "0", width: "100%"}
- if content_for?(:header)
= yield(:header)
%tr
%td.content-wrap.aligncenter
%table{cellpadding: "0", cellspacing: "0", width: "100%"}
= yield
.footer
%table{width: "100%"}
%tr
%td.aligncenter.content-block
Questions? Email
= mail_to mailer.message.from.first
%td
-# left blank deliberately
Bonus: keep your uninlined styles separated
There are some emails that Roadie won’t apply in a style
attribute on the markup elements; that will be added in a <style>
tag at the top. Having those will make your layouts grow unnecessarily, so it’s best to keep markup and style separated. Also, you might want to use some of your SASS variables or mix-ins on this CSS and you should be able to do so!
To get this working elegantly, you can create a CSS file for those styles, add it to the config.assets.precompile
directive, and finally, use a helper method (on the helper included in your mailers) to load your uninlined CSS into the layout:
# ...
def non_inlined_style_tag(name)
style_file = if Rails.application.config.assets.compile
Rails.application.assets.find_asset(name)
else
# if our asset pipeline is disabled
read_stylesheet_from_filesystem(name) # Read a file by name, wit exception handling
end
if style_file.present?
content_tag :style, style_file.to_s.html_safe, type: "text/css", data: { roadie_ignore: true }
end
end
# ...
Note the data-roadie-ignore
attribute which replaces the data-immutable
that was in use in Roadie 2.
Finally, below the stylesheet_link_tag
in your layout, add:
= non_inlined_style_tag :your_file_name
And you’re all set! For reference, here are a couple of links that might be of help:
- SO: How to inline CSS when using the asset pipeline
- GH: Sprockets-Rails issue about pipeline assets being nil in production
Conclusion
I hope this helps fellow devs in the future. May your emails look beautiful wherever they may go!
Finally, I’d like to extend a big shout out to Magnus Bergmark, creator of Roadie, for his contributions and making our lives easier. Tack så mycket!
Main image is “roadie” by Manuel Guastella/NukAgency (on Flickr), used under the BY-NC-ND Creative Commons License