Models
Defining accessors
Any class can be extended to add Dragonfly attachment functionality.
Let’s say you have a model with methods image_uid
and image_uid=
Then you can add the Dragonfly attachment methods image
and image=
with
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_save
and 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
Set to nil
to remove it
We can inspect properties of the attribute
We can add analyser methods (see Analysers), e.g. the ImageMagick plugin adds
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 Job
objects).
We can add processor methods (see Processors), e.g. the ImageMagick plugin adds
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 retained_<attribute_name>
, e.g.
Persisting
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.
URLs
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.
Reflection methods
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
Validations
validates_presence_of
and validates_size_of
work out of the box, and Dragonfly also provides validates_property
.
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 nil
).
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.
Meta data
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.
Default content
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
Callbacks
after_assign
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_assign
callback.
after_unassign
after_unassign
is similar to after_assign
, but is only called when the attachment is unassigned
Up-front processing
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 copy_to
.
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
Storage options
Some datastores take options when calling store
- you can pass these through with storage_options
.
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).
or
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 before_save
,
at which point the id
won’t yet exist.
"Magic" Attributes
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 name
, size
and any of the registered analysis methods (e.g. width
),
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.
Derived from theme by orderedlist