Open-source project
markevans/dragonfly avatar
markevans/dragonfly

Dragonfly: Ruby image processing on demand, not at upload time

A Ruby gem for on-the-fly processing - suitable for image uploading in Rails, Sinatra and much more!

2,106 stars241 forksRubyMIT

At a glance

What is it?
Dragonfly is a Ruby gem that generates image variants when they are first requested rather than pre-processing them at upload. It runs in Rails and Sinatra, supports custom processors for arbitrary media formats, and carries a security fix in v1.4.x for CVE-2021-33564.
Who is it for?
Dragonfly suits Rails and Sinatra apps that need image variants generated on request. It fits when thumbnail dimensions change without schema migrations, or when custom media processors are needed alongside image uploads.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 83 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

On-demand processing and the dragonfly_accessor attachment pattern

Dragonfly's central design is that image variants are not computed at upload time. A user uploads an original, and a 300x200 crop does not exist until a browser first requests the URL carrying those processing instructions. Deferring work to first-request time means the datastore holds only the original until a derived version is actually needed.

At the model level, dragonfly_accessor connects Dragonfly to an ActiveRecord column. Adding it to a model class tells Dragonfly to treat that column as an attachment point, giving the model instance methods for storing, retrieving and processing the attached file. From the view side, method calls like thumb stack up processing steps on a job object; calling .url finalises the job and returns a URL that Dragonfly answers on first request.

Storage stays lean, but first requests for any new size take computation time. Pre-processing all thumbnail sizes at upload avoids that first-request cost but requires deciding the full set of sizes at upload time, which means a schema change or a background migration when a new size is needed later. Dragonfly sidesteps that migration cost at the price of first-request latency.

Installing dragonfly and generating a thumbnail in a Rails view

Installing from RubyGems is the standard path. Adding it to a project uses a Gemfile entry:

ruby
gem 'dragonfly', '~> 1.4.2'

After bundling, require the library:

ruby
require 'dragonfly'

Adding the accessor to an ActiveRecord model wires the column:

ruby
class User < ActiveRecord::Base  # model
  dragonfly_accessor :photo
end

In the view, thumb takes a geometry string in ImageMagick format. A geometry string of '300x200#' means crop to exactly 300 by 200 pixels. Wrapping the tag in a photo_stored? guard avoids rendering when the column is empty:

erb
<%= image_tag @user.photo.thumb('300x200#').url if @user.photo_stored? # view %>

At this point the URL is live, but the datastore needs configuration before uploads land anywhere. Datastore setup is deferred to the documentation at markevans.github.io/dragonfly, which covers local filesystem, S3 and other backends.

Text image generation on demand in Sinatra

Dragonfly is not limited to file uploads. Its generate method creates an asset from parameters rather than from a stored file. Text image generation in Sinatra is one example; the README shows a route where each request path segment becomes image content:

ruby
get "/:text" do |text|
  Dragonfly.app.generate(:text, text, "font-size" => 32).to_response(env)
end

Each GET request triggers a fresh generation call with the path parameter as text and a font size of 32. Calling to_response(env) converts the job result directly to a Rack response, bypassing any persistent storage. No uid is created and nothing is stored in the datastore unless store is called explicitly.

Plugins extend the generate method; the built-in :text generator is one example, and the add-ons wiki documents others. Server-side text overlays, dynamic label images and any case where the asset content is determined by request parameters rather than a prior upload fall within this pattern.

Fetching remote media, running custom processors and storing the result

A pipeline for transforming remote media appears in the README:

ruby
wav = Dragonfly.app.fetch_url("http://free.music/lard.wav")
mp3 = wav.to_mp3
uid = mp3.store
url = Dragonfly.app.remote_url_for(uid)

Every call except store returns a job object. Calling store commits the processed file to the configured datastore and returns a uid string that Dragonfly uses to locate the asset. Calling remote_url_for converts that uid to an external URL; the README's example shows an S3 URL as the result.

In this example, to_mp3 is described as a custom processor, meaning it is not part of Dragonfly's default installation. Processors extend what the job chain can do. Community-written processors are listed in the add-ons wiki. Anyone building a pipeline for formats other than images has to locate or write the relevant processor before the chain can run.

Sample files in the repository include a .docx alongside JPG, PNG, GIF and JP2 images, showing that attachment handling is not limited to image types even though image processing is the most documented use case.

CVE-2021-33564 and what setting verify_urls to false exposes

An explicit security notice appears in the README. CVE-2021-33564 affects installations where verify_urls has been set to false, which the README marks as not recommended. Version 1.4.x contains the fix, and the README directs affected users to upgrade.

No description of the vulnerability mechanism appears in the notice itself. It names the CVE identifier, states that verify_urls false is the condition, and gives the remediation version. Full technical details are at the CVE record at cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-33564.

For any production deployment that ever passed verify_urls false to Dragonfly's configuration, upgrading to 1.4.x is the stated remediation. Placing the security notice in the main README body rather than a separate security file makes it harder to miss during a dependency review.

json gem 1.5.2 incompatibility for non-ASCII filenames

A known issue in the README involves a conflict with json gem version 1.5.2. Files with non-ASCII characters in their names produce an "incorrect sha" error; GitHub issue 387 in the dragonfly repository has the full discussion.

Scope is narrow: both json gem 1.5.2 and a non-ASCII filename are required for the error to appear. Applications where all uploaded filenames are ASCII, or where the json gem is at a different version, do not hit this. No workaround appears in the README; the issue tracker thread is the reference for current status.

For a multilingual application that accepts uploads from users whose systems produce non-ASCII filenames, confirming the json gem version and the filename encoding policy matters before relying on Dragonfly in production.

Off-site documentation, the add-ons wiki and four external resources

As a file, the README is intentionally brief. Its central instruction is to read the documentation at markevans.github.io/dragonfly, and it also links to four additional resources: an articles and tutorials wiki, an add-ons wiki for community-written processors, RDoc at rubydoc.info, and a dragonfly-users Google group for questions.

Datastore configuration, processor registration and application setup are all deferred to the documentation site. A developer following only the README will have a gem installed and a model accessor declared, but no working upload path until they read the documentation for their target datastore.

A push to the master branch last occurred on 2026-07-21. Dragonfly is MIT licensed, and the LICENSE file is at the repository root.

Editorial conclusion

Dragonfly suits Rails and Sinatra apps that need image variants generated on request. It fits when thumbnail dimensions change without schema migrations, or when custom media processors are needed alongside image uploads. Any installation that set verify_urls to false should upgrade to v1.4.x for the CVE-2021-33564 fix. The json gem 1.5.2 incompatibility affects only non-ASCII filenames, so check your upload naming pattern in multilingual contexts. Start at markevans.github.io/dragonfly for datastore and processor configuration; the README does not document those steps.

Frequently asked questions

How do I install Dragonfly in a Rails app?

Add gem 'dragonfly', '~> 1.4.2' to your Gemfile, run bundle, and add require 'dragonfly' to your application. Then call dragonfly_accessor with the attachment column name inside the ActiveRecord model class.

What is the CVE-2021-33564 vulnerability in Dragonfly?

It affects installations where verify_urls has been set to false, which the README marks as not recommended. Upgrading to version 1.4.x contains the fix.

Does Dragonfly work with Sinatra?

Yes. The README shows a Sinatra route that calls Dragonfly.app.generate to produce a text image from a URL path parameter and returns it directly as a Rack response without storing it.

Can Dragonfly handle file types other than images?

The README shows a pipeline that fetches a WAV file, runs a custom to_mp3 processor, stores the result and returns a remote URL. The sample files in the repository include a DOCX alongside image formats.

Where is the Dragonfly documentation?

The main documentation is at markevans.github.io/dragonfly. The README also links to a wiki for articles and tutorials, an add-ons wiki, RDoc at rubydoc.info, and a dragonfly-users Google group.

Official sources

  1. Issues
  2. License: MIT
  3. markevans/dragonfly on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/markevans-dragonfly.svg)](https://hysenlabs.com/projects/markevans-dragonfly)