by Bjorn Forsberg
Ferrum is a pure Ruby gem, providing a high-level API to control Chrome, which runs headless by default. Ferrum is a great alternative to Node's Puppeteer library, which is a pain to use with Ruby and Heroku.
Ferrum can be used for any browser scripting work, as well as for generating screenshots and PDFs. We use it mainly for PDF generation, hosted on Heroku, and the setup flow goes like this:
- Add Chromium locally if not already done:
brew install chromium
- Add
gem "ferrum"
to Gemfile - Add the needed code to your app, which handles generating the PDF file (simplified example):
url = "https://example.com/"
filename = "My file name".parameterize
tmp = Tempfile.new("pdf-chrome-#{filename}")
browser = Ferrum::Browser.new
browser.go_to(url)
sleep(0.3) # Simple way to handle slow JS
browser.pdf(
path: tmp.path,
format: :A4,
landscape: false,
margin: {top: 36, right: 36, bottom: 36, left: 36},
preferCSSPageSize: true,
printBackground: true
)
browser.quit
pdf_data = File.read(tmp.path)
pdf_filename = filename + ".pdf"
send_data(pdf_data, filename: pdf_filename, type: "application/pdf", disposition: "inline")
- Test and commit
- Add the chrome buildpack to Heroku, as the first buildpack in the list:
heroku buildpacks:add heroku/google-chrome --index 1
You should then see:
Buildpack added. Next release on your-app-name will use:
1. heroku/google-chrome
2. heroku/ruby
- Add the following config variable, to tell Heroku/Ferrumwhere it can find the installed Chrome browser:
heroku config:set BROWSER_PATH="/app/.apt/usr/bin/google-chrome"
- Commit and push the changes to git + heroku, all done!
Sidenote: When migrating from Puppeteer to Ferrum, my Heroku slug size also got roughly 200Mb smaller, and deploys are much quicker due to needing fewer buildpacks 🎉