-
Notifications
You must be signed in to change notification settings - Fork 244
Upgrading from 0.9 to 1.0
Most of the changes in 1.0 affect the configuration and writing custom processors, rather than general usage of Dragonfly.
Here is a basic flow for upgrading most rails apps.
- comment out references in your code to
Dragonfly[:my_app_name]
and model dragonfly accessors (e.g.image_accessor
) - update Gemfile to dragonfly
"~>1.0.3"
and bundle install -
mv config/initializers/dragonfly.rb old_dragonfly.rb
(keeping it temporarily for reference) -
rails generate dragonfly
to generate a new config/initializers/dragonfly.rb - Update references to Dragonfly apps anywhere in your code
- If you're using just one Dragonfly app (the default) then e.g.
Dragonfly[:images]
becomesDragonfly.app
- If you're using more than one then e.g.
Dragonfly[:images]
andDragonfly[:assets]
becomesDragonfly.app(:images)
andDragonfly.app(:assets)
- Check insertion of Dragonfly::Middleware (in dragonfly.rb/application.rb/environment files)
- If using just one Dragonfly app then it should already be inserted in config/initializers/dragonfly.rb so you can remove it from other places (like application.rb, .rb, etc.)
- If you're using more than one Dragonfly app then add a line for each in config/initializers/dragonfly.rb
Rails.application.middleware.use Dragonfly::Middleware, :images
Rails.application.middleware.use Dragonfly::Middleware, :assets
- Check correct usage of rack-cache - see http://markevans.github.io/dragonfly/rails#caching
- Update dragonfly.rb with any custom configuration you had in old_dragonfly.rb, but with the new syntax - see the sections below for more details. Afterwards you can delete old_dragonfly.rb
- Change
xxx_accessor
todragonfly_accessor
in models
- If using multiple Dragonfly apps then add the
:app
option to specify which app the accessor refers to (not necessary if only using one) e.g.dragonfly_accessor :app => :images
- See "ImageMagick Changes" below for any changes in imagemagick processors/generators
Phew! Hopefully that is all!!
Previously Dragonfly apps were all named and referred to using e.g.
Dragonfly[:images]
Apps are still named, but are referred to using
Dragonfly.app(:images)
However... there is now a default app
Dragonfly.app
For most purposes, you will only need to use the default app.
Previously you'd first define a macro
app.define_macro(ActiveRecord::Base, :image_accessor)
Then use it in a model
class MyModel < ActiveRecord::Base
image_accessor :image
end
to define a model attachment accessor.
Now there's just one macro method, dragonfly_accessor
, and you simply extend your class with Dragonfly::Model
and use it
class MyModel
extend Dragonfly::Model
dragonfly_accessor :image
end
to use with a named Dragonfly app, e.g. Dragonfly.app(:assets)
, pass the :app option:
dragonfly_accessor :image, app: :assets
Previously middleware was mounted with the app name
use Dragonfly::Middleware, :assets
It still is for named apps, however to mount the default app (which you'll usually be doing), there's no need for an argument
use Dragonfly::Middleware
Previously configuration blocks yielded an object
app.configure do |c|
c.url_format = "..."
end
now nothing is yielded and most xxx=
methods are just xxx
app.configure do
url_format "..."
end
c.datastore = Dragonfly::DataStorage::FileDataStore.new
c.datastore.configure do |d|
d.root_path = "some/path"
end
becomes
datastore :file, root_path: 'some/path'
- i.e. no block, just an options hash, and standard data stores are configured with a symbol.
These have all been extracted into their own gems:
- S3: https://github.com/markevans/dragonfly-s3_data_store
- Mongo: https://github.com/markevans/dragonfly-mongo_data_store
- Couch: https://github.com/markevans/dragonfly-couch_data_store
Instead of implementing store
and retrieve
, these should respond to write
and read
.
They are much the same, although they take a Dragonfly::Content
object now, not a Dragonfly::TempObject
(which has a similar interface, plus a few extra things like mime_type
).
Content not found is signalled by returning nil
from read
, not by raising a Dragonfly::DataStorage::DataNotFound
error.
The file 'dragonfly/rails/images' no longer exists - instead use the provided generator
rails generate dragonfly
Rack::Cache is NOT inserted by Dragonfly - see http://markevans.github.io/dragonfly/rails for more info.
Meta data is now assumed to be serializable to and from JSON, so e.g. image.meta[:name]
should become image.meta['name']
Below are some more version 0.9 configuration options and their 1.0 equivalents
c.response_headers['X-Something'] = '...'
is now
response_header 'X-Something', '...'
and
c.cache_duration = 1000000
c.content_filename = proc{...}
c.content_disposition = :attachment
no longer exist - you can customise these response headers yourself using
response_header 'Cache-Control', 'public, max-age=1000000'
response_header 'Content-Disposition' do |job, request, headers|
'attachment; filename="..."'
end
If using fetch_file
and fetch_url
:
c.allow_fetch_file = true
c.allow_fetch_url = true
have been replaced by whitelists
fetch_file_whitelist [
"/home/images",
/public/
]
fetch_url_whitelist [
"http://localhost:5000/image.png",
/some\.domain/
]
If you need pre-Dragonfly-v0.9.12 urls to work, you'll need to do
allow_legacy_urls true
which now defaults to false.
c.fallback_mime_type = 'something/mental'
no longer exists (not really necessary)
c.log = Logger.new($stdout)
is no longer done on a per-app basis, but for the whole of Dragonfly:
Dragonfly.logger = Logger.new($stdout)
The following no longer exists:
c.trust_file_extensions = false
The mime type for the response "Content-Type" header is derived from the file extension (i.e. the extension is implicitly trusted). If you want to do any format validation or customise the "Content-Type" response header then they can do that yourself according to the requirements of your app.
URL options:
c.url_format = '...'
c.url_host = '...'
c.protect_from_dos_attacks = true
c.secret = 'This is my secret yeh!!'
simply become
url_format '...'
url_host '...'
protect_from_dos_attacks true
secret 'This is my secret yeh!!'
Mime-types:
c.register_mime_type(:egg, 'fried/egg')
is now
mime_type 'egg', 'fried/egg'
Remote serving options:
c.define_url do ... end
end
c.server.before_serve do ... end
is now
define_url do ... end
end
before_serve do ... end
(note no .server
)
.jpg
, .png
and .gif
processors no longer exist - use encode('png')
instead or create your own processor.
.strip
, .crop
, .flip
, .flop
, .resize
, .resize_and_crop
and .greyscale
processors no longer exist - use thumb
instead or you can easily create your own processor
.depth
, .number_of_colours
no longer exist - create your own analyser
.convert("some args", :jpg)
becomes .convert("some args", "format" => "jpg")
.generate(:plain, 400, 300, colour, :format => :gif)
becomes .generate(:plain, 400, 300, 'color' => colour, 'format' => 'gif')
.generate(:plasma, 10, 10, :gif)
becomes .generate(:plasma, 10, 10, 'format' => 'gif')
Previously you could customise imagemagick using
app.configure do |c|
c.convert_command = "/opt/local/bin/convert"
c.identify_command = "/opt/local/bin/identify"
c.log_commands = true
end
Now these are passed to the call to plugin
, and log_commands
doesn't exist (it does log shell commands when the logger is set to debug mode).
app.configure do
plugin :imagemagick,
convert_command: "/opt/local/bin/convert"
identify_command: "/opt/local/bin/identify"
end
There are no longer "encoders" - they were much the same as processors anyway, with the added ability to change the url and Content-Type response to reflect the new format, (e.g. jpeg -> png). Processors can now do this anyway so any "encoding" is now just done by processors.
Arguments passed to processors should be serializable to and from JSON
Processors now define a method on Job/Attachment objects, so instead of using
image.process(:optimize, 30)
you can use
image.optimize(30)
Previously registered processors took a Dragonfly::TempObject
and returned something
c.processor.add :optimize do |temp_object, amount|
tempfile = Tempfile.new(['dragonfly','png'])
tempfile.binmode
tempfile.close
`optimize -a#{amount} -out "#{tempfile.path}" "#{temp_object.path}"`
tempfile
end
Now they take a Dragonfly::Content
, and update it, rather than returning anything. It has convenience methods to make using the shell and using other processors easier.
processor :optimize do |content, amount|
content.shell_update, ext: 'png' do |old_path, new_path|
"optimize -a#{amount} -out #{old_path} #{new_path}"
end
end
Note c.processor.add
simply becomes processor
.
Previously you could register all the public methods of a class as processors
class MyProcessor
def resize(temp_object, *args)
# ...
end
def crop(temp_object, *args)
# ...
end
end
app.configure do |c|
c.processor.register(MyProcessor) # registers resize and crop
end
You can no longer do this, and must register each in turn, either as a block or as an object that responds to call
class MyCropProcessor
def call(content, *args)
# ...
end
end
app.configure do
processor :resize do |content, *args|
# ...
end
processor :crop, MyCropProcessor.new
end
This way processors can individually implement update_url
to update the url when they're used (optional - see http://markevans.github.io/dragonfly/processors#implementing-the-processor).
The same goes for analysers and generators.
Previously you could define a shortcut using job
, e.g. to do
image.black_and_white('30x30')
we'd configure
c.job :black_and_white do |size|
process :greyscale
process :thumb, size
encode :gif
end
This is unnecessary, because defining a black_and_white
processor now defines a black_and_white
method on Job/Attachment objects, and processors can now access other processors using Content#process!
.
So instead of using job
we just define another processor
processor :black_and_white do |content, size|
content.process!(:greyscale)
content.process!(:thumb, size)
content.process!(:encode, 'gif')
end
Actually we could have used content.process!(:thumb, size, 'format' => 'gif')
in the example above but you get the idea.
Previously we used
app.configure_with(:imagemagick)
We can still do this, but it's easier to use plugin
inside a configuration block:
plugin :imagemagick
Custom plugins now need to implement call
, not apply_configuration
.
The default logger will now be dragonfly.log
Set it to Rails.logger to streamline it.
Dragonfly.logger = Rails.logger