Dragonfly

Image/asset management for winners

GitHub Repository

Data stores

Data stores are key-value stores that store a piece of content with meta (the value) and reference it with a string uid (the key).

Dragonfly uses these to store data which can later be fetched, e.g.

Given any Dragonfly job

job = Dragonfly.app.generate(:text, "lublug").thumb('x200')

it can be stored with

uid = job.store   # ===> "2013/11/06/12_38_39_606_taj.jpg"

and later fetched with

Dragonfly.fetch(uid)

Models

Models simply hold a reference to the uid and do the storing and fetching behind the scenes at the appropriate times - see Models for more details.

File data store

This is the default, but it can be manually configured using

Dragonfly.app.configure do
  datastore :file
  # ...
end

or with options

datastore :file,
  :root_path => 'public/dragonfly',    # directory under which to store files
                                       # - defaults to 'dragonfly' relative to current dir
  :server_root => 'public'             # root for urls when serving directly from datastore
                                       #   using remote_url

You can specify the storage path per-content with

uid = job.store(:path => 'my/custom/path')

To see how to do this with models, see Models - Storage Options

Memory data store

The Memory data store keeps everything in memory and is useful for things like tests.

To use:

Dragonfly.app.configure do
  datastore :memory
  # ...
end

You can also specify the uid on store

uid = job.store(:uid => "179")

Other data stores

The following datastores previously in Dragonfly core are now in separate gems:

Building a custom data store

Data stores need to implement three methods: write, read and destroy.

class MyDataStore

  # Store the data AND meta, and return a unique string uid
  def write(content, opts={})
    some_unique_uid = SomeLibrary.store(content.data, meta: content.meta)
    some_unique_uid
  end

  # Retrieve the data and meta as a 2-item array
  def read(uid)
    data = SomeLibrary.get(uid)
    meta = SomeLibrary.get_meta(uid)
    if content
      [
        data,     # can be a String, File, Pathname, Tempfile
        meta      # the same meta Hash that was stored with write
      ]
    else
      nil         # return nil if not found
    end
  end

  def destroy(uid)
    SomeLibrary.delete(uid)
  end

end

The above should be fairly self-explanatory, but to be a bit more specific:

write

  • takes a content object (see Dragonfly::Content for more details) and uses a method like data (String), file, path to get its data and meta to get its meta
  • also takes an options hash, passing through any options passed to store
  • returns a unique String uid

read

  • takes a String uid
  • returns a 2-item array; the data in the form of a String, Pathname, File or Tempfile and the meta hash
  • returns nil instead if not found

destroy

  • takes a String uid
  • destroys the content

You can also optionally serve data directly from the datastore using

Dragonfly.app.remote_url_for(uid)

or

my_model.attachment.remote_url

provided the data store implements url_for

class MyDataStore

  # ...

  def url_for(uid, opts={})
    "http://some.domain/#{uid}"
  end

end

Both remote_url_for and remote_url also take an options hash which will be passed through to the data store’s url_for method.

Using your custom data store

Your custom data store can be used by a Dragonfly app with

Dragonfly.app.configure do
  datastore MyDataStore.new(:some => 'args')
  # ...
end

or you can register a symbol (which you may want to do if creating a gem)

Dragonfly::App.register_datastore(:my_data_store){ MyDataStore }

so you configure using just the symbol

Dragonfly.app.configure do
  datastore :my_data_store, :some => 'args'
  # ...
end

Note that the data store class is registered with the symbol, not the instance. Any other args are passed straight to the data store’s initialize method.

Testing with RSpec

Dragonfly provides a shared rspec example group that you can use to test that your custom data store conforms to the basic spec. Here’s a simple example spec file

require 'spec_helper'
require 'dragonfly/spec/data_store_examples'

describe MyDataStore do

  before(:each) do
    @data_store = MyDataStore.new
  end

  it_should_behave_like 'data_store'

end