Send PDF attachments from Rails with WickedPdf and ActionMailer

In almost any web application you create, the question of generating PDF files will pop up pretty soon. There are a couple of options while using Ruby on Rails. First one is Prawn which is a pure PDF generator library, and the other options are mostly wrappers around the very popular wkhtmltopdf unix library that converts html pages to pdf. There is also an option that uses PrinceXML but I would initially exclude it because it is pretty pricey for an SME.

While using Prawn gives you all of the formatting power when creating PDF files, it’s learning curve is pretty steep, and the option of converting html to a PDF seems pretty good. This is especially the case when you already have html templates that only need some small modifications to be able to convert them to PDF.

There are a couple of gems that wrap around the wkhtmltopdf library, and ruby-toolbox pdf generation section shows some more viable options that can be used when generating PDF files from ruby.

I’ll be using WickedPdf in this example, as that is the one I have set up this system with a couple of times already, so I’m pretty confident it will work in any other Rails application.


As always, using a ruby gem in rails is pretty simple, you just add a couple of lines to the Gemfile

gem 'wicked_pdf'
#we need the new binary here, so that we can be OS independent
gem 'wkhtmltopdf-binary', github: 'pallymore/wkhtmltopdf-binary-edge', tag: 'v0.12.2'


This setup will work pretty straightforward in the controllers, because WickedPdf registers :pdf request format, and you can respond to it in the same fashion as html or js in a respond_to block. Code below is copied from the WickedPdf Readme page.

class ThingsController < ApplicationController
  def show
    respond_to do |format|
      format.pdf do
        render pdf: "file_name" # Excluding ".pdf" extension.

That part was pretty easy, and you can configure the pdf render with a lot of options that are mentioned in the advanced configuration section of the WickedPdf Readme

Generating PDF from ActionMailer

The issue when trying to generate the PDF from ActionMailer is that there is no request, so you have to render the html in a different way. In a nutshell, you want to render the template to a string, and then forward that string (html) to the wkhtmltopdf. This is the same way the gem work when rendering pdf from the controller, but it is worth mentioning once more.

We will use a method that exists on the AbstractController::Rendering and it is called render_to_string So we can do something like this in the mailer:

class TodoMailer < ActionMailer::Base
  def pdf_attachment_method(todo_id)
    todo = Todo.find(todo_id)
    attachments["todo_#{}.pdf"] =
      render_to_string(pdf: 'todo', template: 'todo.pdf.erb', layout: 'pdf.html'), { :hash_with_wickedpdf_options }
    mail(to:, subject: 'Your todo PDF is attached', todo: todo)

By using this approach, we can easily send a PDF attachment from an ActionMailer method. You can do this for any Rails template you want, but be sure to test everything before putting it into production.

Speed up Rails on Heroku by using Rack::Zippy

I really like Heroku for fast deployments and everything they offer for a small Ruby on Rails or node.js apps. It’s so easy to deploy a web app there, and it’s pretty much free unless you are doing some serious stuff, by when you should already be paying either Heroku, or have your own dedicated solution when you’re all grown up.

There is one thing that I personally dislike about Heroku, and that is their asset serving. As we are all sitting behind a desktop(laptop) computer, and have pretty good network connections, we don’t see how slow the app is for someone on 3G mobile network, or something even slower. And in a well written app, the main culprit for large data transfers are the assets.

We have a lot of JavaScript, Css and images in our apps, because we want to make them beautiful, but that takes it’s toll on network bandwidth. Luckily most browsers support compressed assets(js and css) and know how to decompress them. And when you build your own server, there is a very high probability that assets won’t be served through Rails at all. You will either use NGINX or Apache httpd to act as a reverse proxy, and also serve your assets for you. The web server is smart enough to serve compressed assets to browsers that support them, and uncompressed to others.

Rails has a pretty good ActionDispatch::Static rack middleware that does all the work for us while in development, or on heroku by changing a config flag, or using their rails_12factor gem in production. To get it running you have to change the static flag inside the config/environments/production.rb

 # rails 4.1 and below
 config.serve_static_assets = true
 # rails 4.2 and above
 config.serve_static_files = true

For those on a budget, and not able to afford to serve assets from Amazon S3 or another CDN (will update here when my post on how to do that is finished), there is an option on serving the compressed assets from rails. They are already generated by heroku on deploy, but just aren’t being served, which considerably increases your initial page load time, and every additional one, if the assets aren’t being properly cached. ` You can solve this pretty big issue with including one gem that will serve compressed assets for you. It’s called Rack::Zippy and it’s really easy to configure. You have to add it to the Gemfile first:

gem 'rack-zippy'

Run the bundle command and create the initializer for Rack::Zippy in config/initializers/rack_zippy.rb like this:

Rails.application.config.middleware.swap(ActionDispatch::Static, Rack::Zippy::AssetServer)

This will use Rack::Zippy to server gzipped assets instead of uncompressed ones and really reduce your initial load time, especially on slow connections. It also adds pretty sane cache expiration headers which can also help with the browser caching.

Use Rack::Deflater to get faster first time loads of your app

Is your Ruby on Rails application slow for end users? Maybe you are sending a lot of data through the network. As we rarely test performance on our basic server to client setup, and I don’t mean the maxed out broadband speeds we like to have at our places of work, but regular DSL, or mobile internet user, with the minimal internet speed available.
We also have the false security while browser testing the application on the same machine we develop it on. And it’s really fast to fetch 10MB from localhost:3000 into the browser.
Do you think that pulling even a 1MB response is nice when the DSL speed is 2mbps and that means around 4 seconds to fetch it. Only your assets can grow to that size if you are not careful, and this is far from the response size of larger websites. For example, has a payload of ~1.5MB (at least at the time of writing, my front page). And it takes around 4.55 seconds to render on my DSL which is around 10mbps. For a regular DSL user (~2mbps) the time it takes is 8 seconds, and the difference is, of course, the time it takes to receive the 1.5MB of data. For a mobile user it takes even longer because let’s be honest, no one can achieve those claimed 150mbps LTE speeds.
There is a very quick solution to reduce the payload of your Rails (and other Rack based apps) by including just one line of code in yours config/application.rb.

config.middleware.use Rack::Deflater

That will automatically deflate your server responses (which is a fancy word for compression that the browser knows how to uncompress), and you will be serving substantially smaller responses. Of course, your web server must be configured to enable compression, and there is a great guide for that here.

Learning Ruby and Rails in 2014

In the last few weeks, I have been approached by a couple of people who are interested in learning Ruby and/or Ruby on Rails. And for their sake, and for my own interest, I investigated what are the best resources at the moment. Ruby and Rails ecosystem is a one that evolves really fast, and while I like it a lot, because we have new toys to play with all of the time, it is not a great thing for new developers. Also Rails has grown to this big behemoth, and although I like Rails a lot, and will continue using it as long as I can, I’m not sure it is newbie friendly. But I’ll address that one later.

Before i list the resources, and their brief descriptions, there are a couple of rules you should follow, to have an easy ride with Ruby on rails. A basic understanding of HTML/CSS is needed, because, you are learning a web framework, which incidentally runs in the browser, which incidentally uses HTML/CSS to render the pages. I’m not telling you that you need to be a frontend developer/designer, just to have a basic knowledge of it. Ok, no more philosophy from now on. You should also be acquainted with JavaScript, not that you need to be an expert in it, but just have a basic knowledge of it. You are going to use it if you want to have any dynamic interactions in your web applications, but it is not as crucial as HTML/CSS. After you have your prerequisites in order (and it will probably take you a couple of days to get acquainted with HTML/CSS and JavaScript), you can start learning a new programming language, and a web framework. The basics will come in handy if decide to use any other programming language and framework, if your goal is to create web applications.

Learning Ruby on Rails is mostly done backwards, at least that is the way I’ve done it myself. I first “learned” Ruby on Rails, then started learning Ruby, because it was pretty stupid not being skilled in a language that runs your favorite web framework. Who would of thought that by learning the language, you get to understand the framework better. You should not be a fool that I was, and learn the language first. Also, learning Ruby on Rails is a really big bite to chew all at once. Here is a brief overview of the things you are expected to learn all at once:

  • A new language
  • A whole web framework and its abstractions
  • HTML/CSS (if you haven’t done web development before)
  • JavaScript (or CoffeeScript and its abstractions)
  • Probably much more stuff that I don’t remember anymore

Learning Ruby

First thing you want to know is how Ruby syntax looks like, and how it behaves. I think that the best possible way to find out is to Try Ruby. This is a great interactive tutorial, which helps you to learn the language basics. There is also one more site, which I’ve been using lately, to get an insight into other programming languages: Learn X in Y minutes and specifically their Ruby tutorial. After you have done the ruby tutorials, and at least grasped the language basics, you will be able to decide if you like it or not. If you chose not to experience the awesomeness of Ruby, and everything that comes with it, that is OK. To each their own. If you want to continue learning ruby, this is probably the best book there is: Programming Ruby or colloquially called “The Pickaxe book”, from which you will not only learn about the Ruby programming language, but there are also three Regex chapters from which you can learn to be a wizard.

Learning Ruby web frameworks

After you have learned Ruby, the next step on your itinerary is learning Ruby on Rails. I would like you to make a short break here, and learn something a bit closer to the metal. Sinatra is a great small Ruby web framework which will teach you how to build small and simple sites or API endpoints. Also, it is possible to mount Sinatra apps in Rails, and the Rails learning curve will be easier for you if you already know Sinatra. And maybe you decide that Sinatra, with some added libraries is enough for your project. So as a next step, I want you to look into Padrino which is built upon Sinatra, and it also gives you a predefined way to build your web applications.

Learning Ruby on Rails

Learning Ruby on Rails is a big task, and if you set out to do it, it can take you 15 minutes to build a blog, and probably half a decade to master everything that Rails can (and will be able to) do. In my opinion, the best resource to get you on the way is The Ruby on Rails Tutorial by Michael Hartl. A book (and videos) that have helped mold plenty of Ruby on Rails developers. There is also a free online version, if you are on a budget. There is of course the official Ruby on Rails Guides, and one of my favorite books on Rails, The Rails 4 Way which is a great resource, and each time I get through it, I find another new thing I should be using. There is (was) a great screencast resource packaged in Railscasts. Although it isn’t updated anymore (I really hope Ryan gets back soon), it is still a great asset for solving most of the specific problems you will encounter as a Rails developer.

I have focused mostly on free resources, although some of the books I recommend come with a price tag attached. The price, although it might seem a lot to you, is really reasonable, and is much lower than the value these books provide. Even if you don’t stick with Ruby, owning The Pickaxe Book, and going through the first part of it, will teach you some stuff you can probably employ in your language of choice.

I however, chose Ruby, and I’m happy with it. And it doesn’t mean I am, or will only be doing Ruby for the rest of my life (I probably could, if you don’t count JavaScript), but that Ruby on Rails solves the database backed web application problem in the best way I can imagine. And if that isn’t your game, you probably didn’t get to this part of the post. If you have, please try Ruby, it is a beautiful programming language that was designed to make developers happy.

Rails No-No's: Not using background processing

Have you encountered a website with a very slow response? How do you feel when you have to wait for 5 or more seconds, for the page to even start responding? How do you feel when the app you are waiting for ages, is something you are paying for on a monthly basis? Fuck this, let’s try something different? Yep, that is the same thing your users (customers) are feeling when your app is waiting for something. And users have the tendency of voting with their wallets, which in this case, can make your much thinner than it is at the moment.

First and foremost issue is sending emails, when the user registers or when they ask for a password renewal. Those situations can even stand sending emails in sync, but you are blocking the web process thread for new requests while the email processing ends. Let’s consider a situation where you have some larger data massaging operation, that hides between a single form submit. Take for example large business reports, which have to collect data from a number of different data sources, both internal and external. Now, this process can take from a couple of seconds, to hours if your data is not well optimized. You are basically wasting that person’s time on waiting for the report to finish. Now multiply the average time that a person waits, with their hourly rate and that with the average number of reports someone waits for, and with the number of people running such reports in a given company. That is a serious waste of money right there, now if you could somehow optimize this process, you could stand to easily save $10,000+ on lost time, and more over the lifespan of the application.

Imagine if the users abandoned your shopping cart, while it was processing something that could have ran in the background. Now you are losing real sales, and your client is on their way of either firing you, or going broke.

OK, enough melodrama for now. Let us now consider a different option from doing everything in one process in sync. You have the option of threading, but that won’t get you very far, because you are still blocking the user’s flow, while they wait for the response. Enter background workers, which are best run on a separate machine, and they have queue of tasks that need to be performed. A set number of processes which take handle of those tasks, and report back(if needed) when the task is finished. Here are a few options for background jobs in Ruby on Rails:

  • Sidekiq – Multi threaded background processing built on Celluloid::IO and actor based model
  • Delayed::Job – One of the first, if not the first background workers for rails, extracted from Shopify
  • Resque – Background worker using redis instead of the database for queuing jobs

I’ve been using all of them over the years, but as of a year ago, I have been using only Sidekiq on new and migrated some old applications from other workers to it. The benefit of Sidekiq is using actor model and threads to process jobs concurrently, it has a low memory footprint and can be used to boost your application performance, and responsiveness. If you are on Heroku, this will cost you one worker instance per month, as that should be enough to process a very large number of background jobs. If you are running your own stack, one server with the minimum hardware requirements will suffice. No one cares if their email is delivered in 3 minutes instead of right now. But they do care if they can’t do anything for that 3 minutes while waiting for “something to finish”. Here is a basic example of how it’s done with Sidekiq:

class UserGeoLocator
  include Sidekiq::Worker

  def perform(user_id)
    user = User.find(user_id)

You can find out all the things it can be used for in the Sidekiq Wiki on Github.

Rails No-No's: Using inline CoffeeScript with Haml

I’ve always had a love-hate relationship with HAML, partly because if the css is clean, it can be a great thing, and if it isn’t then your markup will look really ugly. But that is not the thing I’m writing about now. This is about something else, using inline CoffeeScript inside Haml templates. As you know, you really shouldn’t be using inline JavaScript at all, but you can get by, especially if you have some weird use cases. The thing with CoffeeScript is that  it has to get compiled each time into JavaScript, which is fine, if you are using something like Sprockets to compile it on deployment, but if you are using the feature Haml provides you to shoot yourself in the foot, you can cause some serious performance issues for your site.
Consider the two following snippet:

  %h1 Some nice headline

  $('h1').click ->
  alert('You clicked on the headline')

If you put that in the template, you are causing yourself with a hit of about 100-200ms that takes to compile that coffescript into javascript, and then inline it. But if you try doing this:

  %h1 Some nice headline

  $('h1').click(function() {
    alert('You clicked on the headline');

Then the performance hit is mostly gone. You still have a code smell in your views, but not a one that will cause a drastic performance loss if you don’t remove it right away.
But if you consider a situation in which you render nested partials, and each one of them has some inline coffeescript, which I myself have done unknowingly before, that will multiply the issue with the amount of rendered partials. You can of course count on rails caching to save your ass, and it will most of the times, but not always. And then you will have that one customer who waits for more than 10 seconds to get their page.

If by any means you want to reduce the maintenance nightmare, you will be very fast to remove inline javascript from the code all together, which will most probably also optimise your javascript code, and make it more maintainable in the future.

Refresh your elasticsearch index with zero downtime

I’m using a basic elasticsearch-rails setup on one of the applications I’m working on. The thing is, we sometimes need to make changes to the ES index, add new fields, or redo the existing ones. And when you have a database that needs at least 10 minutes(it was closer to 1 hour before we reworked the implementation), you can’t really afford that downtime. As ES-rails sets things up for you in a certain way, it was needed to use some of the underlying ES features to get the job done correctly.

So, it was needed to completely remove the downtime while doing the full reindex(deleting and creating the elasticsearch index). If you are already using elasticsearch-rails then you are familiar with the nomenclature, and probably with the methods described. For doing a complete reindex we require a rake task to do the job for us like this:

namespace :elasticsearch do
  task :reindex => :environment do
    index_name = Person.index_name
    Person.__elasticsearch__.create_index! force: true
    Person.all.find_in_batches(batch_size: 1000) do |group|
      group_for_bulk = do |a|
        { index: { _id:, data: a.as_indexed_json } }
        index: index_name,
        type: "person",
        body: group_for_bulk

This will effectively remove the index if it exists and reload the new data in the index, making it practically unusable until the task is done. Because this wasn’t an option, we looked into ES aliases and found them to be helpful. Basically, what we needed to do was to create an index with a unique name, and assign an alias to it, so that we could create and fill the index while the current one was still operational. So no downtime needed.

index_name = "#{Person.index_name}_#{SecureRandom.hex}"
client = Person.__elasticsearch__.client
Person.__elasticsearch__.create_index! index: index_name, force: true
Person.all.find_in_batches(batch_size: 1000) do |group|
# to be sure there is no index named Person.index_name
client.indices.delete(index: Person.index_name) rescue nil
  # collecting old indices
  old_indices = client.indices.get_alias(name: Person.index_name).map do |key, val|
    { index: key, name: val['aliases'].keys.first }
  # creating new alias
  client.indices.put_alias(index: index_name, name: Person.index_name)
  # removing old indices
  old_indices.each do |index|
    client.indices.delete(index: index[:index])

So that is about it, you just call bin/rake elasticsearch:reindex and you have refreshed your elasticsearch index with zero downtime. Of course, you will have to implement some system to track the changed records while you were reindexing(remember we are working on a live system, so data is changing all the time). We used redis for that, to mark when reindexing has started $redis.set('elasticsearch:reindex_running', true) collected all changed record ids in a redis array, processed them via the regular indexing worker, and deleted the key after the alias was linked with $redis.del('elasticsearch:reindex_running').

Override https errors for regular http calls

Let’s say you are building a web app that has some secure user data involved
in the picture. You have to secure it with https, that is a necessity. So what
happens when you have to include some outside service into your https only
application, and the service sadly doesn’t have an https site, or maybe it has
a self signed certificate? The error pops up, something in the context of This page is only
partialy secure
There is a way to override this, but you are doing it at you own risk. You
really should use only verified https resources in your public facing sites.

There can be many reasons why you would go with this solution, and i’ll leave
them to you to find that out by yourself, i’m just giving you the hammer.

So, you want to override https calls in your app, and it’s a rails app(this
approach can be done using sinatra or anything else ruby based, if you don’t
know how to implement it, contact me and i’ll try to help)

Basically you want to override the outside http call with a call to your own
application, yes this can hurt your performance, but not having a green icon in
the address bar can hurt you even more. I’ll make an example with a simple
JSON call to an external service, but it can be done with any call.

First you should set up a controller to handle these requests, lets say
ExternalResourcesController make an external_json method and add it to the
routes.rb file, of course you need net/http and uri for making the
remote calls.

# app/controllers/external_resources_controller.rb
require ‘net/http’
require ‘uri’
class ExternalResourcesController < ApplicationController def external_json options = { # fill your options with the params you are sending from the application } uri = URI('some external json service url') uri.query = URI.encode_www_form(options) resp = Net::HTTP.get(uri) render json: resp end end [/ruby] [ruby] # config/routes.rb get 'external_resources/external_json', to: 'external_resources#external_json' [/ruby] This approach also gives you the benefit of not having to send and expose all parameters you are sending in client facing JavaScript, and can only send the dynamic ones. That can pay off if you are using this call more than once. And you can call this from your CoffeeScript very easily: [javascript] # app/assets/javascripts/ json = $.ajax url: "/external_resources/external_json" dataType: "jsonp" data: first_param_name: "I'm a parameter" second_param_name: "I'm a parameter too" [/javascript] Once again, you should only use this approach if you really, really know what you are doing, i’m not liable for the problems you can cause.

Calculating distance using geo coordinates in ruby

As the social part of the sites is growing stronger, everyone of us has to
include a user’s location of some sort into the application. There can be many
reasons for that, be it location based search, advertising or something else
unrelated. But mark this, you will have to deal with locations in the future.

I won’t get into the details of how to get the user’s latitude and longitude,
but geocoder gem could be helpful for you.

I have found one JavaScript solution with the descriptions of what are the
different implementations of the calculation and which one is more correct so
I won’t get into the explanation. You can check the explanation and even more
stuff you can do with 2 geo coordinates on the Movable Type Scripts

The distance can be calculated using 3 formulas, Haversine, Spherical
Law of Cosines
, and Equirectangular approximation

The prerequisites we will need are degree to radian conversion which is easily
done with degree / 180 * Math::PI but to make the code easier to write we
can monkey patch the Float with to_rad method which will calculate this for
us. We could use refinements, or make a method object and not pollute the
global space but we can leave it like this for now.

class Float
  def to_rad
    self / 180 * Math::PI

After we have done the prerequisites let’s assume that we have two objects,
and each one has a latitude and a longitude. For the sake of this post we can
make them a hash with two keys latitude and longitude. And we take the
earth radius as 6371km

class Geodistance
  include Math
  attr_reader :from, :to, :lat1, :lon1, :lat2, :lon2
  RADIUS = 6371
  def initialize(from, to)
    @from = from
    @to = to
  def distance(type = 'haversine')
      raise NotImplementedError, 'The type you have requested is not implemented, try "cosines" or "approximation", or without params for "haversine"'
  def haversine
    d_lat = (from[:latitude] - to[:latitude]).to_rad
    d_lon = (from[:longitude] - to[:longitude]).to_rad
    a = sin(d_lat / 2) * sin(d_lat / 2) + sin(d_lon / 2) *
      sin(d_lon / 2) * cos(lat1) * cos(lat2)
    c = 2 * atan2(sqrt(a), sqrt(1-a))
    RADIUS * c
  def cosines
    acos(sin(lat1) * sin(lat2) +
         cos(lat1) * cos(lat2) *
         cos(lon2 - lon1)) * RADIUS
  def approximation
    x = (lon2 - lon1) * cos((lat1 + lat2) / 2)
    y = lat2 - lat1
    sqrt(x * x + y * y) * RADIUS
  def set_variables
    @lat1 = from[:latitude].to_rad
    @lat2 = to[:latitude].to_rad
    @lon1 = from[:longitude].to_rad
    @lon2 = to[:longitude].to_rad

As you can see by calling the distance method with all 3 parameters, each one
will produce a slightly different result. As they say, the haversine one
should be the most accurate, but take caution. I would like to benchmark them
some day and see which one calculates the result faster.

Thanks to Movable Type Scripts for providing the JavaScript
code and all the insight. I just did a rewrite in Ruby.

Rails Integration testing with MiniTest::Spec and Capybara

So you want to do integration testing for your application, good for you. If you have chosen MiniTest and it’s specing DSL MiniTest::Spec  as your test framework here is an example how to setup the integration tests to run fairly fast. Integration tests are similar to Cucubmer features, if you have used that before. I just like this style better because Cucumber, IMO adds too much noise, but it serves you as application documentation. I will also user Capybara for the webpage testing.
Because we are using minitest-spec-rails gem, we don’t need to tinker with the config/application.rb and test settings, because ActiveSupport::TestCase is a subclass of MiniTest::Spec

First we will set up the gemfile, with the needed gems( I also use guard for my automated tests, but it’s worth writing another blog post, soon hopefully)

group :development, :test do
  gem 'minitest-spec-rails'
  gem 'capybara_minitest_spec' # for capybara integration and spec matchers
  gem 'capybara-webkit' # for headless javascript tests
  gem 'turn' # for prettier test output

After that we need to set up out test/test_helper.rb to use Turn and capybara

require 'rubygems'
require 'rails/test_help'
require 'minitest/autorun'
require 'capybara/rails'
require 'turn'

class ActionDispatch::IntegrationTest
  include Rails.application.routes.url_helpers # for x_path and x_url helpers
  include Capybara::DSL
  include PossibleJSDriver # switching Capybara driver for javascript tests, look below

# switching to the javascript driver in integration tests
module PossibleJSDriver
  def require_js
    Capybara.current_driver = :webkit

  def teardown
    Capybara.current_driver = nil

After you have everything set up you can use all of this in your integration tests, here is an example of one integration test, without and with javascript browser turned on(require_js turns on the webkit driver)

require ‘test_helper’
class LoginTest < ActionDispatch::IntegrationTest before { visit login_path } describe "signup text" do it "must have a signup text" do page.must_have_content("Don't have an account?") end it "must have a signup link" do page.find_link('Sign up').wont_be_nil end it "signup link must go to the signup path" do require_js # this one turns on the webkit javascript driver click_link('Sign up') current_path.must_equal(signup_path) end end end [/ruby] I have tested the integration test speed with :webkit as a default capybara driver and it runs at the same speed as the normal :rack_test driver, so you can go that way too. Resources used: