Any class can be extended to add Dragonfly attachment functionality.
Let’s say you have a model with methods
Then you can add the Dragonfly attachment methods
To define an accessor using a named (i.e. non-default) Dragonfly app such as
you can pass a the app name as an option
If the model class responds to
before_destroy (like with ActiveRecord) then
the attachment will be stored on save (when changed) and destroyed on destroy.
To extend all ActiveRecord models, you can do
Using the accessors
We can use the attribute much like other other model attributes:
When setting with a string you should also set a name so that Dragonfly knows its mime-type
nil to remove it
We can inspect properties of the attribute
We can play around with the data
see How does it work? - Using the content for more examples (
Attachment objects work in a similar way to
Assigning from a URL
Dragonfly provides an accessor for assigning directly from a url:
You can put this in a form view, e.g. in rails erb:
It also works for data uris
Removing an attachment via a form
Normally unassignment of an attachment is done like any other attribute, by setting to nil
but this can’t be done via a form - instead
remove_<attachment_name> is provided, which can be used with a checkbox:
Retaining across form redisplays
When a model fails validation, you don’t normally want to have to upload your attachment again, so you can avoid having to do this by
including a hidden field in your form
When the model is saved, a before_save callback persists the data to the Dragonfly app’s configured datastore. The uid column is then filled in.
Once the model is saved, we can get a url for the image which will be served by Dragonfly, and for its processed versions.
Because the processing methods are lazy, no processing is actually done in the above code.
xxx_stored? tells you if the content has been stored in the data store.
It’s useful for deciding whether the url is available or not
xxx_changed? tells you if the content has been changed since saving.
It’s useful for deciding whether to validate or not
validates_size_of work out of the box, and Dragonfly also provides
validates_property will work for any property, not just Dragonfly analysers, because internally it simply calls
send on the attribute.
It does nothing if the accessor is not set (i.e. returns
It can also take a proc for the message
Name and extension
If the object assigned is a file, or responds to
original_filename (as is the case with file uploads in Rails, etc.), then
name will be set.
You can store metadata along with the content data of your attachment:
NOTE meta must be serializable to/from JSON, i.e. consist of strings, numbers, booleans, NOT symbols, dates, etc.
Meta data can be useful because at the time that Dragonfly serves content, it doesn’t have access to your model, but it does have access to the meta data that was stored alongside the content, so you could use it to provide custom response headers, etc.
Normally if an accessor is not set it returns nil
However we can get it to return something by default by giving a path
the Job object returned is equivalent to
after_assign can be used to do something every time content is assigned:
Inside the block, you can call methods on the model instance directly (
self is the model):
Alternatively you can pass in a symbol, corresponding to a model instance method:
You can register more than one
after_unassign is similar to
after_assign, but is only called when the attachment is unassigned
The best way to create different versions of content such as thumbnails is generally on-the-fly, however if you must
create another version on-upload, then you could create another accessor and automatically copy to it using
In the above example you would need both a
mugshot_uid field and a
smaller_mugshot_uid field on your model.
You can also do this manually (e.g. in a background task) using
Some datastores take options when calling
store - you can pass these through with
For example, the file datastore takes a
:path option to specify where to store the content (which will also become the uid for that content).
BEWARE!!!! you must make sure the path (which will become the uid for the content) is unique and changes each time the content is changed, otherwise you could have caching problems, as the generated urls will be the same for the same uid.
BEWARE No. 2!!!! using
id in the
storage_path won’t generally work on create, because Dragonfly stores the content in a call to
at which point the
id won’t yet exist.
An accessor like
image only relies on the accessor
image_uid to work.
However, in some cases you may want to record some other properties, whether it be for using in queries, or
for caching an attribute for performance reasons, etc.
For the properties
size and any of the registered analysis methods (e.g.
this is done automatically for you, if the corresponding accessor exists.
For example - with ActiveRecord, given the migration:
This will automatically be set when assigned:
They can be used to avoid retrieving data from the datastore for analysis
Furthermore, any magic attributes you add a field for will be added to the meta data for that attachment, so can be used to set custom response headers when Dragonfly serves the content.