oahu-dragonfly 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.yardopts +24 -0
- data/Gemfile +30 -0
- data/History.md +323 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/config.ru +14 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +297 -0
- data/extra_docs/Analysers.md +66 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +124 -0
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +153 -0
- data/extra_docs/Encoding.md +67 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +60 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/ImageMagick.md +125 -0
- data/extra_docs/Index.md +33 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +272 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +77 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +57 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +28 -0
- data/features/support/env.rb +13 -0
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
- data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
- data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
- data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
- data/fixtures/rails_3.0.5/template.rb +20 -0
- data/irbrc.rb +18 -0
- data/lib/dragonfly.rb +55 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
- data/lib/dragonfly/analyser.rb +58 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
- data/lib/dragonfly/app.rb +172 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +6 -0
- data/lib/dragonfly/config/rails.rb +20 -0
- data/lib/dragonfly/configurable.rb +207 -0
- data/lib/dragonfly/core_ext/array.rb +7 -0
- data/lib/dragonfly/core_ext/hash.rb +7 -0
- data/lib/dragonfly/core_ext/object.rb +12 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/couch_data_store.rb +64 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
- data/lib/dragonfly/function_manager.rb +71 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
- data/lib/dragonfly/image_magick/analyser.rb +51 -0
- data/lib/dragonfly/image_magick/config.rb +41 -0
- data/lib/dragonfly/image_magick/encoder.rb +57 -0
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +99 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +4 -0
- data/lib/dragonfly/job.rb +451 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +20 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/rails/images.rb +27 -0
- data/lib/dragonfly/response.rb +97 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/server.rb +113 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/temp_object.rb +175 -0
- data/lib/dragonfly/url_mapper.rb +78 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +1426 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
- data/spec/dragonfly/app_spec.rb +135 -0
- data/spec/dragonfly/configurable_spec.rb +461 -0
- data/spec/dragonfly/core_ext/array_spec.rb +19 -0
- data/spec/dragonfly/core_ext/hash_spec.rb +19 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
- data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +173 -0
- data/spec/dragonfly/job_spec.rb +1046 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +47 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/server_spec.rb +278 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/temp_object_spec.rb +306 -0
- data/spec/dragonfly/url_mapper_spec.rb +126 -0
- data/spec/functional/deprecations_spec.rb +51 -0
- data/spec/functional/image_magick_app_spec.rb +27 -0
- data/spec/functional/model_urls_spec.rb +85 -0
- data/spec/functional/remote_on_the_fly_spec.rb +51 -0
- data/spec/functional/to_response_spec.rb +31 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +47 -0
- data/spec/support/simple_matchers.rb +53 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +89 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +544 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
Configuration
|
2
|
+
=============
|
3
|
+
|
4
|
+
Given a Dragonfly app
|
5
|
+
|
6
|
+
app = Dragonfly[:app_name]
|
7
|
+
|
8
|
+
Configuration can either be done like so...
|
9
|
+
|
10
|
+
app.configure do |c|
|
11
|
+
c.url_path_prefix = '/media'
|
12
|
+
# ...
|
13
|
+
end
|
14
|
+
|
15
|
+
...or directly like so...
|
16
|
+
|
17
|
+
app.url_path_prefix = '/media'
|
18
|
+
|
19
|
+
The defaults should be fairly sensible, but you can tweak a number of things if you wish.
|
20
|
+
Here is an example of an app with all attributes configured:
|
21
|
+
|
22
|
+
app.configure do |c|
|
23
|
+
c.datastore = SomeCustomDataStore.new :egg => 'head' # defaults to FileDataStore
|
24
|
+
|
25
|
+
c.cache_duration = 3600*24*365*2 # defaults to 1 year # (1 year)
|
26
|
+
c.fallback_mime_type = 'something/mental' # defaults to application/octet-stream
|
27
|
+
c.log = Logger.new($stdout) # defaults to Logger.new('/var/tmp/dragonfly.log')
|
28
|
+
c.trust_file_extensions = false # defaults to true
|
29
|
+
|
30
|
+
c.url_path_prefix = '/images' # defaults to nil
|
31
|
+
c.url_host = 'http://some.domain.com:4000' # defaults to nil
|
32
|
+
c.url_suffix = '.jpg' # defaults to nil - has no effect other than change the url
|
33
|
+
|
34
|
+
c.content_filename = proc{|job, request| # defaults to the original name, with modified ext if encoded
|
35
|
+
"file.#{job.ext}"
|
36
|
+
}
|
37
|
+
c.content_disposition = :attachment # defaults to nil (use the browser default)
|
38
|
+
|
39
|
+
c.protect_from_dos_attacks = true # defaults to false - adds a SHA parameter on the end of urls
|
40
|
+
c.secret = 'This is my secret yeh!!' # should set this if concerned about DOS attacks
|
41
|
+
|
42
|
+
c.analyser.register(MyAnalyser) # See 'Analysers' for more details
|
43
|
+
c.processor.register(MyProcessor, :type => :fig) # See 'Processing' for more details
|
44
|
+
c.encoder.register(MyEncoder) do |e| # See 'Encoding' for more details
|
45
|
+
e.some_value = 'geg'
|
46
|
+
end
|
47
|
+
c.generator.register(MyGenerator) # See 'Generators' for more details
|
48
|
+
|
49
|
+
c.register_mime_type(:egg, 'fried/egg') # See 'MimeTypes' for more details
|
50
|
+
|
51
|
+
c.job :black_and_white do |size| # Job shortcut - lets you do image.black_and_white('30x30')
|
52
|
+
process :greyscale
|
53
|
+
process :thumb, size
|
54
|
+
encode :gif
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Where is configuration done?
|
59
|
+
----------------------------
|
60
|
+
In Rails, it should be done in an initializer, e.g. 'config/initializers/dragonfly.rb'.
|
61
|
+
Otherwise it should be done anywhere where general setup is done, early on.
|
62
|
+
|
63
|
+
Saved configurations
|
64
|
+
====================
|
65
|
+
Saved configurations are useful if you often configure the app the same way.
|
66
|
+
There are a number that are provided with Dragonfly:
|
67
|
+
|
68
|
+
ImageMagick
|
69
|
+
-----------
|
70
|
+
|
71
|
+
app.configure_with(:imagemagick)
|
72
|
+
|
73
|
+
The {Dragonfly::ImageMagick::Config ImageMagick configuration} registers the app with the {Dragonfly::ImageMagick::Analyser ImageMagick Analyser}, {Dragonfly::ImageMagick::Processor ImageMagick Processor},
|
74
|
+
{Dragonfly::ImageMagick::Encoder ImageMagick Encoder} and {Dragonfly::ImageMagick::Generator ImageMagick Generator}, and adds the 'job shortcuts'
|
75
|
+
`thumb`, `jpg`, `png`, `gif` and `convert`.
|
76
|
+
|
77
|
+
The file 'dragonfly/rails/images' does this for you.
|
78
|
+
|
79
|
+
The processor, analyser, encoder and generator pass data around using tempfiles.
|
80
|
+
|
81
|
+
Rails
|
82
|
+
-----
|
83
|
+
|
84
|
+
app.configure_with(:rails)
|
85
|
+
|
86
|
+
The {Dragonfly::Config::Rails Rails configuration} points the log to the Rails logger, configures the file data store root path, sets the url_path_prefix to /media, and
|
87
|
+
registers the {Dragonfly::Analysis::FileCommandAnalyser FileCommandAnalyser} for helping with mime_type validations.
|
88
|
+
|
89
|
+
The file 'dragonfly/rails/images' does this for you.
|
90
|
+
|
91
|
+
Heroku
|
92
|
+
------
|
93
|
+
|
94
|
+
app.configure_with(:heroku, 's3_bucket_name')
|
95
|
+
|
96
|
+
The {Dragonfly::Config::Heroku Heroku configuration} configures it to use the {Dragonfly::DataStorage::S3DataStore}, using Heroku's config attributes.
|
97
|
+
See {file:Heroku} for more info.
|
98
|
+
|
99
|
+
Custom Saved Configuration
|
100
|
+
--------------------------
|
101
|
+
You can create your own saved configuration with any object that responds to 'apply_configuration':
|
102
|
+
|
103
|
+
module MyConfiguration
|
104
|
+
|
105
|
+
def self.apply_configuration(app, *args)
|
106
|
+
app.configure do |c|
|
107
|
+
c.url_path_prefix = '/hello/beans'
|
108
|
+
c.processor.register(MyProcessor)
|
109
|
+
# ...
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
Then to configure:
|
116
|
+
|
117
|
+
app.configure_with(MyConfiguration, :any_other => :args) # other args get passed through to apply_configuration
|
118
|
+
|
119
|
+
You can also carry on configuring by passing a block
|
120
|
+
|
121
|
+
app.configure_with(MyConfiguration) do |c|
|
122
|
+
c.any_extra = :config_here
|
123
|
+
# ...
|
124
|
+
end
|
data/extra_docs/Couch.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
CouchDB
|
2
|
+
=====
|
3
|
+
Dragonfly can be used with any ActiveModel-compatible model, and so you can use it with CouchDB using [CouchRest::Model](https://github.com/couchrest/couchrest_model).
|
4
|
+
|
5
|
+
Since CouchDB allows you to store files directly on documents as attachments, you can also use the supplied {Dragonfly::DataStorage::CouchDataStore CouchDataStore}.
|
6
|
+
which allows storing files as attachments directly on documents.
|
7
|
+
|
8
|
+
For more info about ActiveModel, see {file:Models}.
|
9
|
+
|
10
|
+
For more info about using the Couch data store, see {file:DataStorage}.
|
11
|
+
|
12
|
+
Example setup in Rails, using CouchRest::Model
|
13
|
+
-------------------------------------
|
14
|
+
In config/initializers/dragonfly.rb:
|
15
|
+
|
16
|
+
require 'dragonfly'
|
17
|
+
|
18
|
+
app = Dragonfly[:images]
|
19
|
+
|
20
|
+
# Get database config from config/couchdb.yml
|
21
|
+
couch_settings = YAML.load_file(Rails.root.join('config/couchdb.yml'))[Rails.env]
|
22
|
+
|
23
|
+
# Configure to use ImageMagick, Rails defaults, and the Couch data store
|
24
|
+
app.configure_with(:imagemagick)
|
25
|
+
app.configure_with(:rails) do |c|
|
26
|
+
c.datastore = Dragonfly::DataStorage::CouchDataStore.new(
|
27
|
+
:host => couch_settings['host'],
|
28
|
+
:port => couch_settings['port'],
|
29
|
+
:username => couch_settings['username'],
|
30
|
+
:password => couch_settings['password'],
|
31
|
+
:database => couch_settings['database']
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Allow all CouchRest::Model models to use the macro 'image_accessor'
|
36
|
+
app.define_macro(CouchRest::Model::Base, :image_accessor)
|
37
|
+
|
38
|
+
# ... any other setup, see Rails docs
|
39
|
+
|
40
|
+
Then in models:
|
41
|
+
|
42
|
+
class Album < CouchRest::Model::Base
|
43
|
+
property :cover_image_uid
|
44
|
+
image_accessor :cover_image
|
45
|
+
|
46
|
+
# ...
|
47
|
+
end
|
48
|
+
|
49
|
+
See {file:Models} for more info.
|
@@ -0,0 +1,153 @@
|
|
1
|
+
Data Storage
|
2
|
+
============
|
3
|
+
|
4
|
+
Each dragonfly app has a key-value datastore to store the content (originals only).
|
5
|
+
|
6
|
+
Lets say we have an app
|
7
|
+
|
8
|
+
app = Dragonfly[:my_app_name]
|
9
|
+
|
10
|
+
Then we can store data like so:
|
11
|
+
|
12
|
+
uid = app.store('SOME CONTENT') # Can pass in a String, File or Tempfile
|
13
|
+
|
14
|
+
We can also save metadata at the same time, and give it a name and format (if you pass in a File object the filename is used by default)
|
15
|
+
|
16
|
+
uid = app.store('SOME CONTENT',
|
17
|
+
:meta => {:time => Time.now},
|
18
|
+
:name => 'great_content.txt',
|
19
|
+
:format => :txt
|
20
|
+
)
|
21
|
+
|
22
|
+
We can get content with
|
23
|
+
|
24
|
+
content = app.fetch(uid)
|
25
|
+
content.data # "SOME CONTENT"
|
26
|
+
|
27
|
+
We can also get the extra saved attributes
|
28
|
+
|
29
|
+
content.meta # {:time => Sat Aug 14 12:04:13 +0100 2010}
|
30
|
+
content.name # 'great_content.txt'
|
31
|
+
content.format # :txt
|
32
|
+
|
33
|
+
We can destroy it with
|
34
|
+
|
35
|
+
app.destroy(uid)
|
36
|
+
|
37
|
+
You can create your own datastore, or use one of the provided ones as outlined below.
|
38
|
+
|
39
|
+
File datastore
|
40
|
+
--------------
|
41
|
+
The {Dragonfly::DataStorage::FileDataStore FileDataStore} stores data on the local filesystem.
|
42
|
+
|
43
|
+
It is used by default.
|
44
|
+
|
45
|
+
If for whatever reason you need to configure it again:
|
46
|
+
|
47
|
+
# shouldn't need this - it is the default
|
48
|
+
app.datastore = Dragonfly::DataStorage::FileDataStore.new
|
49
|
+
|
50
|
+
app.datastore.configure do |d|
|
51
|
+
d.root_path = '/my/custom/path' # defaults to /var/tmp/dragonfly
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
S3 datastore
|
56
|
+
------------
|
57
|
+
To configure with the {Dragonfly::DataStorage::S3DataStore S3DataStore}:
|
58
|
+
|
59
|
+
app.datastore = Dragonfly::DataStorage::S3DataStore.new
|
60
|
+
|
61
|
+
app.datastore.configure do |d|
|
62
|
+
c.bucket_name = 'my_bucket'
|
63
|
+
c.access_key_id = 'salfjasd34u23'
|
64
|
+
c.secret_access_key = '8u2u3rhkhfo23...'
|
65
|
+
end
|
66
|
+
|
67
|
+
You can also pass these options to `S3DataStore.new` as an options hash.
|
68
|
+
|
69
|
+
|
70
|
+
Mongo datastore
|
71
|
+
---------------
|
72
|
+
To configure with the {Dragonfly::DataStorage::MongoDataStore MongoDataStore}:
|
73
|
+
|
74
|
+
app.datastore = Dragonfly::DataStorage::MongoDataStore.new
|
75
|
+
|
76
|
+
It won't normally need configuring, but if you wish to:
|
77
|
+
|
78
|
+
app.datastore.configure do |d|
|
79
|
+
c.host = 'http://egg.heads:5000' # defaults to localhost
|
80
|
+
c.port = '27018' # defaults to mongo default (27017)
|
81
|
+
c.database = 'my_database' # defaults to 'dragonfly'
|
82
|
+
c.username = 'some_user' # only needed if mongo is running in auth mode
|
83
|
+
c.password = 'some_password' # only needed if mongo is running in auth mode
|
84
|
+
end
|
85
|
+
|
86
|
+
You can also pass these options to `MongoDataStore.new` as an options hash.
|
87
|
+
|
88
|
+
Couch datastore
|
89
|
+
---------------
|
90
|
+
To configure with the {Dragonfly::DataStorage::CouchDataStore CouchDataStore}:
|
91
|
+
|
92
|
+
app.datastore = Dragonfly::DataStorage::CouchDataStore.new
|
93
|
+
|
94
|
+
To configure:
|
95
|
+
|
96
|
+
app.datastore.configure do |d|
|
97
|
+
c.host = 'localhost' # defaults to localhost
|
98
|
+
c.port = '5984' # defaults to couchdb default (5984)
|
99
|
+
c.database = 'dragonfly' # defaults to 'dragonfly'
|
100
|
+
c.username = '' # not needed if couchdb is in 'admin party' mode
|
101
|
+
c.password = '' # not needed if couchdb is in 'admin party' mode
|
102
|
+
end
|
103
|
+
|
104
|
+
You can also pass these options to `CouchDataStore.new` as an options hash.
|
105
|
+
|
106
|
+
Custom datastore
|
107
|
+
----------------
|
108
|
+
Data stores are key-value in nature, and need to implement 3 methods: `store`, `retrieve` and `destroy`.
|
109
|
+
|
110
|
+
class MyDataStore
|
111
|
+
|
112
|
+
def store(temp_object, opts={})
|
113
|
+
# ... use temp_object.data, temp_object.file, temp_object.path, etc. ...
|
114
|
+
# store and return the uid
|
115
|
+
'return_some_unique_uid'
|
116
|
+
end
|
117
|
+
|
118
|
+
def retrieve(uid)
|
119
|
+
# return an array containing
|
120
|
+
[
|
121
|
+
content, # either a File, String or Tempfile
|
122
|
+
extra_data # Hash with optional keys :meta, :name, :format
|
123
|
+
]
|
124
|
+
end
|
125
|
+
|
126
|
+
def destroy(uid)
|
127
|
+
# find the content and destroy
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
You can now configure the app to use your datastore:
|
133
|
+
|
134
|
+
Dragonfly[:my_app_name].datastore = MyDataStore.new
|
135
|
+
|
136
|
+
Notice that `store` takes a second `opts` argument.
|
137
|
+
Any options other than `meta`, `name` and `format` get passed through to here, so calling
|
138
|
+
|
139
|
+
uid = app.store('SOME CONTENT',
|
140
|
+
:name => 'great_content.txt',
|
141
|
+
:some_other => :option
|
142
|
+
)
|
143
|
+
|
144
|
+
will be split inside `store` like so:
|
145
|
+
|
146
|
+
def store(temp_object, opts={})
|
147
|
+
temp_object.data # "SOME CONTENT"
|
148
|
+
temp_object.name # 'great_content.txt'
|
149
|
+
opts # {:some_other => :option}
|
150
|
+
# ...
|
151
|
+
end
|
152
|
+
|
153
|
+
# ...
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Encoding
|
2
|
+
========
|
3
|
+
Registered encoders change the format of data, e.g. a jpeg image to a png image.
|
4
|
+
|
5
|
+
You can register as many encoders as you like.
|
6
|
+
|
7
|
+
Let's say we have a Dragonfly app
|
8
|
+
|
9
|
+
app = Dragonfly[:images]
|
10
|
+
|
11
|
+
and an image object (actually a {Dragonfly::Job Job} object)...
|
12
|
+
|
13
|
+
image = app.fetch('some/uid')
|
14
|
+
|
15
|
+
...OR a Dragonfly model accessor...
|
16
|
+
|
17
|
+
image = @album.cover_image
|
18
|
+
|
19
|
+
We can encode it to any format registered with the encoder.
|
20
|
+
|
21
|
+
Lazy evaluation
|
22
|
+
---------------
|
23
|
+
|
24
|
+
gif_image = image.encode(:gif)
|
25
|
+
|
26
|
+
doesn't actually do anything until you call something on the returned {Dragonfly::Job Job} object, like `url`, `data`, etc.
|
27
|
+
|
28
|
+
Bang method
|
29
|
+
-----------
|
30
|
+
|
31
|
+
image.encode!(:gif)
|
32
|
+
|
33
|
+
modifies the image object itself, rather than returning a new object.
|
34
|
+
|
35
|
+
ImageMagick Encoder
|
36
|
+
-------------------
|
37
|
+
See {file:ImageMagick}.
|
38
|
+
|
39
|
+
Custom Encoders
|
40
|
+
---------------
|
41
|
+
|
42
|
+
To register a custom encoder, for e.g. pdf format:
|
43
|
+
|
44
|
+
app.encoder.add do |temp_object, format|
|
45
|
+
throw :unable_to_handle unless format == :pdf
|
46
|
+
# use temp_object.data, temp_object.path, temp_object.file, etc.
|
47
|
+
SomeLibrary.convert_to_pdf(temp_object.data)
|
48
|
+
# return a String, Pathname, File or Tempfile
|
49
|
+
end
|
50
|
+
|
51
|
+
pdf_image = image.encode(:pdf)
|
52
|
+
|
53
|
+
If `:unable_to_handle` is thrown, the next most recently registered encoder is used, and so on.
|
54
|
+
|
55
|
+
Alternatively you can create a class like the ImageMagick one above, which implements the method `encode`, and register this.
|
56
|
+
|
57
|
+
class MyEncoder
|
58
|
+
|
59
|
+
def encode(temp_object, format, *args)
|
60
|
+
SomeLib.encode(temp_object.data, format, *args)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
app.encoder.register(MyEncoder)
|
66
|
+
|
67
|
+
pdf_image = image.encode(:pdf, :some => :args)
|
@@ -0,0 +1,121 @@
|
|
1
|
+
General Usage
|
2
|
+
=============
|
3
|
+
|
4
|
+
You can have multiple dragonfly apps, each with their own configuration.
|
5
|
+
Each app has a name, and is referred to by that name.
|
6
|
+
|
7
|
+
Dragonfly[:images] # ===> Creates an app called 'images'
|
8
|
+
Dragonfly[:images] # ===> Refers to the already created app 'images'
|
9
|
+
|
10
|
+
app = Dragonfly[:images]
|
11
|
+
|
12
|
+
Getting/generating content
|
13
|
+
--------------------------
|
14
|
+
Three methods can be used to get content:
|
15
|
+
|
16
|
+
app.fetch('some_uid') # Fetch from datastore (default filesystem)
|
17
|
+
|
18
|
+
app.fetch_file('~/path/to/file.png') # Fetch from a local file
|
19
|
+
|
20
|
+
app.generate(:plasma, 400, 300) # Generates using a method from the configured
|
21
|
+
# generator (in this case a plasma image)
|
22
|
+
|
23
|
+
These all return {Dragonfly::Job Job} objects. These objects are lazy - they don't do any fetching/generating until
|
24
|
+
some other method is called on them.
|
25
|
+
|
26
|
+
Using the content
|
27
|
+
-----------------
|
28
|
+
Once we have a {Dragonfly::Job Job} object:
|
29
|
+
|
30
|
+
image = app.fetch('some_uid')
|
31
|
+
|
32
|
+
We can get the data a number of ways...
|
33
|
+
|
34
|
+
image.data # => "\377???JFIF\000\..."
|
35
|
+
image.to_file('out.png') # writes to file 'out.png' and returns a readable file object
|
36
|
+
image.tempfile # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a closed Tempfile object
|
37
|
+
image.file # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a readable (open) File object
|
38
|
+
image.file do |f| # Yields an open file object, returns the return value of
|
39
|
+
data = f.read(256) # the block, and closes the file object
|
40
|
+
end
|
41
|
+
image.path # => '/var/folders/st/strHv74sH044JPabSiODz...' i.e. the path of the tempfile
|
42
|
+
image.size # => 134507 (size in bytes)
|
43
|
+
|
44
|
+
We can get its url...
|
45
|
+
|
46
|
+
image.url # => "/media/BAhbBlsHOgZmIg9hc..."
|
47
|
+
|
48
|
+
We can analyse it (see {file:Analysers} for more info) ...
|
49
|
+
|
50
|
+
image.width # => 280
|
51
|
+
|
52
|
+
We can process it (see {file:Processing} for more info) ...
|
53
|
+
|
54
|
+
new_image = image.process(:thumb, '40x30') # returns another 'Job' object
|
55
|
+
|
56
|
+
We can encode it (see {file:Encoding} for more info) ...
|
57
|
+
|
58
|
+
new_image = image.encode(:gif) # returns another 'Job' object
|
59
|
+
|
60
|
+
Chaining
|
61
|
+
--------
|
62
|
+
Because the methods
|
63
|
+
|
64
|
+
- `fetch`
|
65
|
+
|
66
|
+
- `fetch_file`
|
67
|
+
|
68
|
+
- `generate`
|
69
|
+
|
70
|
+
- `process`
|
71
|
+
|
72
|
+
- `encode`
|
73
|
+
|
74
|
+
all return {Dragonfly::Job Job} objects, we can chain them as much as we want...
|
75
|
+
|
76
|
+
image = app.fetch('some_uid').process(:greyscale).process(:thumb, '40x20#').encode(:gif)
|
77
|
+
|
78
|
+
... and because they're lazy, we don't actually do any processing/encoding until either `apply` is called
|
79
|
+
|
80
|
+
image.apply # actually 'does' the processing and returns self
|
81
|
+
|
82
|
+
... or a method is called like `data`, `to_file`, etc.
|
83
|
+
|
84
|
+
This means we can cheaply generate urls for processed data without doing any fetching or processing:
|
85
|
+
|
86
|
+
url = app.fetch('some_uid').process(:thumb, '40x20#').encode(:gif).url
|
87
|
+
|
88
|
+
and then visit that url in a browser to get the actual processed image.
|
89
|
+
|
90
|
+
Shortcuts
|
91
|
+
---------
|
92
|
+
Commonly used processing/encoding steps can be shortened, so instead of
|
93
|
+
|
94
|
+
app.fetch('some_uid').process(:greyscale).process(:thumb, '40x20#').encode(:jpg)
|
95
|
+
|
96
|
+
we could use something like
|
97
|
+
|
98
|
+
app.fetch('some_uid').grey('40x20#')
|
99
|
+
|
100
|
+
This does exactly the same, returning a {Dragonfly::Job Job} object.
|
101
|
+
|
102
|
+
To define this shortcut:
|
103
|
+
|
104
|
+
app.configure do |c|
|
105
|
+
c.job :grey do |size|
|
106
|
+
process :greyscale
|
107
|
+
process :thumb, size
|
108
|
+
encode :jpg
|
109
|
+
end
|
110
|
+
# ...
|
111
|
+
end
|
112
|
+
|
113
|
+
The {Dragonfly::ImageMagick::Config ImageMagick} configuration comes with the pre-defined shortcuts:
|
114
|
+
|
115
|
+
image.thumb('40x30') # same as image.process(:thumb, '40x30')
|
116
|
+
image.jpg # same as image.encode(:jpg)
|
117
|
+
image.png # same as image.encode(:png)
|
118
|
+
image.gif # same as image.encode(:gif)
|
119
|
+
image.convert('-scale 30x30') # same as image.process(:convert, '-scale 30x30')
|
120
|
+
|
121
|
+
`thumb` and `convert` can optionally take a format (e.g. :gif) as the second argument.
|