dragonfly 0.9.15 → 1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dragonfly might be problematic. Click here for more details.

Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -8
  3. data/.travis.yml +11 -0
  4. data/Gemfile +1 -0
  5. data/History.md +52 -2
  6. data/LICENSE +1 -1
  7. data/README.md +38 -95
  8. data/dev/grid.jpg +0 -0
  9. data/dev/irbrc.rb +27 -0
  10. data/dev/rails_template.rb +38 -0
  11. data/dev/test.ru +56 -0
  12. data/dev/test_rails +19 -0
  13. data/dragonfly.gemspec +3 -21
  14. data/lib/dragonfly.rb +45 -44
  15. data/lib/dragonfly/app.rb +175 -96
  16. data/lib/dragonfly/configurable.rb +71 -170
  17. data/lib/dragonfly/content.rb +211 -0
  18. data/lib/dragonfly/core_ext/object.rb +1 -6
  19. data/lib/dragonfly/file_data_store.rb +197 -0
  20. data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
  21. data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
  22. data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
  23. data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
  24. data/lib/dragonfly/image_magick/generators/text.rb +127 -0
  25. data/lib/dragonfly/image_magick/plugin.rb +83 -0
  26. data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
  27. data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
  28. data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
  29. data/lib/dragonfly/job.rb +118 -134
  30. data/lib/dragonfly/job_endpoint.rb +2 -0
  31. data/lib/dragonfly/memory_data_store.rb +34 -0
  32. data/lib/dragonfly/middleware.rb +5 -3
  33. data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
  34. data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
  35. data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
  36. data/lib/dragonfly/model/class_methods.rb +109 -0
  37. data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
  38. data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
  39. data/lib/dragonfly/railtie.rb +8 -6
  40. data/lib/dragonfly/register.rb +27 -0
  41. data/lib/dragonfly/response.rb +47 -52
  42. data/lib/dragonfly/routed_endpoint.rb +4 -0
  43. data/lib/dragonfly/serializer.rb +15 -5
  44. data/lib/dragonfly/server.rb +56 -29
  45. data/lib/dragonfly/shell.rb +12 -23
  46. data/lib/dragonfly/spec/data_store_examples.rb +64 -0
  47. data/lib/dragonfly/temp_object.rb +32 -47
  48. data/lib/dragonfly/url_attributes.rb +19 -22
  49. data/lib/dragonfly/url_mapper.rb +3 -0
  50. data/lib/dragonfly/utils.rb +12 -0
  51. data/lib/dragonfly/version.rb +1 -1
  52. data/lib/dragonfly/whitelist.rb +19 -0
  53. data/lib/rails/generators/dragonfly/USAGE +8 -0
  54. data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
  55. data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
  56. data/samples/gif.gif +0 -0
  57. data/spec/dragonfly/app_spec.rb +270 -64
  58. data/spec/dragonfly/configurable_spec.rb +142 -418
  59. data/spec/dragonfly/content_spec.rb +353 -0
  60. data/spec/dragonfly/cookie_monster_spec.rb +2 -1
  61. data/spec/dragonfly/file_data_store_spec.rb +301 -0
  62. data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
  63. data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
  64. data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
  65. data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
  66. data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
  67. data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
  68. data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
  69. data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
  70. data/spec/dragonfly/job_endpoint_spec.rb +30 -73
  71. data/spec/dragonfly/job_spec.rb +280 -608
  72. data/spec/dragonfly/memory_data_store_spec.rb +20 -0
  73. data/spec/dragonfly/middleware_spec.rb +47 -27
  74. data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
  75. data/spec/dragonfly/model/validations_spec.rb +196 -0
  76. data/spec/dragonfly/register_spec.rb +35 -0
  77. data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
  78. data/spec/dragonfly/serializer_spec.rb +13 -15
  79. data/spec/dragonfly/server_spec.rb +122 -46
  80. data/spec/dragonfly/shell_spec.rb +43 -24
  81. data/spec/dragonfly/temp_object_spec.rb +69 -94
  82. data/spec/dragonfly/url_attributes_spec.rb +49 -0
  83. data/spec/dragonfly/utils_spec.rb +32 -0
  84. data/spec/dragonfly/whitelist_spec.rb +30 -0
  85. data/spec/dragonfly_spec.rb +43 -0
  86. data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
  87. data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
  88. data/spec/functional/configuration_spec.rb +19 -0
  89. data/spec/functional/model_urls_spec.rb +43 -41
  90. data/spec/functional/remote_on_the_fly_spec.rb +14 -16
  91. data/spec/functional/shell_commands_spec.rb +24 -14
  92. data/spec/functional/to_response_spec.rb +10 -10
  93. data/spec/functional/urls_spec.rb +5 -3
  94. data/spec/spec_helper.rb +23 -28
  95. data/spec/support/argument_matchers.rb +7 -8
  96. data/spec/support/image_matchers.rb +14 -36
  97. data/spec/support/model_helpers.rb +97 -0
  98. data/spec/support/simple_matchers.rb +12 -0
  99. metadata +92 -393
  100. data/.yardopts +0 -29
  101. data/Rakefile +0 -36
  102. data/config.ru +0 -14
  103. data/docs.watchr +0 -1
  104. data/extra_docs/Analysers.md +0 -68
  105. data/extra_docs/Caching.md +0 -23
  106. data/extra_docs/Configuration.md +0 -149
  107. data/extra_docs/Couch.md +0 -49
  108. data/extra_docs/DataStorage.md +0 -226
  109. data/extra_docs/Encoding.md +0 -67
  110. data/extra_docs/ExampleUseCases.md +0 -116
  111. data/extra_docs/GeneralUsage.md +0 -105
  112. data/extra_docs/Generators.md +0 -68
  113. data/extra_docs/Heroku.md +0 -50
  114. data/extra_docs/ImageMagick.md +0 -136
  115. data/extra_docs/Index.md +0 -33
  116. data/extra_docs/MimeTypes.md +0 -40
  117. data/extra_docs/Models.md +0 -441
  118. data/extra_docs/Mongo.md +0 -42
  119. data/extra_docs/Processing.md +0 -77
  120. data/extra_docs/Rack.md +0 -52
  121. data/extra_docs/Rails2.md +0 -57
  122. data/extra_docs/Rails3.md +0 -56
  123. data/extra_docs/ServingRemotely.md +0 -104
  124. data/extra_docs/Sinatra.md +0 -25
  125. data/extra_docs/URLs.md +0 -203
  126. data/features/images.feature +0 -47
  127. data/features/no_processing.feature +0 -14
  128. data/features/rails.feature +0 -8
  129. data/features/steps/common_steps.rb +0 -8
  130. data/features/steps/dragonfly_steps.rb +0 -66
  131. data/features/steps/rails_steps.rb +0 -40
  132. data/features/support/env.rb +0 -13
  133. data/features/support/setup.rb +0 -41
  134. data/fixtures/rails/files/app/models/album.rb +0 -6
  135. data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
  136. data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
  137. data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
  138. data/fixtures/rails/files/features/manage_album_images.feature +0 -38
  139. data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
  140. data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
  141. data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
  142. data/fixtures/rails/files/features/support/paths.rb +0 -17
  143. data/fixtures/rails/files/features/text_images.feature +0 -7
  144. data/fixtures/rails/template.rb +0 -20
  145. data/irbrc.rb +0 -19
  146. data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
  147. data/lib/dragonfly/analyser.rb +0 -58
  148. data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
  149. data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
  150. data/lib/dragonfly/config/heroku.rb +0 -26
  151. data/lib/dragonfly/config/image_magick.rb +0 -6
  152. data/lib/dragonfly/config/rails.rb +0 -20
  153. data/lib/dragonfly/data_storage.rb +0 -11
  154. data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
  155. data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
  156. data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
  157. data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
  158. data/lib/dragonfly/encoder.rb +0 -13
  159. data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
  160. data/lib/dragonfly/function_manager.rb +0 -67
  161. data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
  162. data/lib/dragonfly/generator.rb +0 -9
  163. data/lib/dragonfly/image_magick/analyser.rb +0 -53
  164. data/lib/dragonfly/image_magick/config.rb +0 -44
  165. data/lib/dragonfly/image_magick/encoder.rb +0 -57
  166. data/lib/dragonfly/image_magick/generator.rb +0 -147
  167. data/lib/dragonfly/image_magick/processor.rb +0 -114
  168. data/lib/dragonfly/image_magick/utils.rb +0 -46
  169. data/lib/dragonfly/image_magick_utils.rb +0 -4
  170. data/lib/dragonfly/job_builder.rb +0 -39
  171. data/lib/dragonfly/job_definitions.rb +0 -30
  172. data/lib/dragonfly/loggable.rb +0 -28
  173. data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
  174. data/lib/dragonfly/processor.rb +0 -9
  175. data/lib/dragonfly/rails/images.rb +0 -32
  176. data/lib/dragonfly/simple_cache.rb +0 -23
  177. data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
  178. data/spec/dragonfly/analyser_spec.rb +0 -123
  179. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
  180. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
  181. data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
  182. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
  183. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
  184. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
  185. data/spec/dragonfly/function_manager_spec.rb +0 -154
  186. data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
  187. data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
  188. data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
  189. data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
  190. data/spec/dragonfly/job_builder_spec.rb +0 -37
  191. data/spec/dragonfly/job_definitions_spec.rb +0 -57
  192. data/spec/dragonfly/loggable_spec.rb +0 -80
  193. data/spec/dragonfly/simple_cache_spec.rb +0 -27
  194. data/spec/dragonfly/url_attributes.rb +0 -47
  195. data/spec/functional/deprecations_spec.rb +0 -51
  196. data/spec/functional/image_magick_app_spec.rb +0 -27
  197. data/spec/test_imagemagick.ru +0 -49
  198. data/yard/handlers/configurable_attr_handler.rb +0 -38
  199. data/yard/setup.rb +0 -15
  200. data/yard/templates/default/fulldoc/html/css/common.css +0 -109
  201. data/yard/templates/default/layout/html/layout.erb +0 -93
  202. data/yard/templates/default/module/html/configuration_summary.erb +0 -31
  203. data/yard/templates/default/module/setup.rb +0 -17
@@ -1,42 +0,0 @@
1
- Mongo
2
- =====
3
- Dragonfly can be used with any ActiveModel-compatible model, therefore libraries like [Mongoid](http://mongoid.org) work out of the box.
4
-
5
- Furthermore, Mongo DB has support for storing blob-like objects directly in the database (using MongoDB 'GridFS'),
6
- so you can make use of this with the supplied {Dragonfly::DataStorage::MongoDataStore MongoDataStore}.
7
-
8
- For more info about ActiveModel, see {file:Models}.
9
-
10
- For more info about using the Mongo data store, see {file:DataStorage}.
11
-
12
- Example setup in Rails, using Mongoid
13
- -------------------------------------
14
- In config/initializers/dragonfly.rb:
15
-
16
- require 'dragonfly'
17
-
18
- app = Dragonfly[:images]
19
-
20
- # Configure to use ImageMagick, Rails defaults, and the Mongo data store
21
- app.configure_with(:imagemagick)
22
- app.configure_with(:rails) do |c|
23
- c.datastore = Dragonfly::DataStorage::MongoDataStore.new :db => Mongoid.database
24
- end
25
-
26
- # Allow all mongoid models to use the macro 'image_accessor'
27
- app.define_macro_on_include(Mongoid::Document, :image_accessor)
28
-
29
- # ... any other setup, see Rails docs
30
-
31
- Then in models:
32
-
33
- class Album
34
- include Mongoid::Document
35
-
36
- field :cover_image_uid
37
- image_accessor :cover_image
38
-
39
- # ...
40
- end
41
-
42
- See {file:Models} for more info.
@@ -1,77 +0,0 @@
1
- Processing
2
- ==========
3
- Registered processors allow you to modify data, e.g. resizing an image.
4
-
5
- You can register as many processors 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 process it using any processing methods that have been registered with the processor.
20
-
21
- Lazy evaluation
22
- ---------------
23
-
24
- new_image = image.process(:some_method)
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.process!(:some_method)
32
-
33
- modifies the image object itself, rather than returning a new object.
34
-
35
- ImageMagick Processor
36
- ---------------------
37
- See {file:ImageMagick}.
38
-
39
- Custom Processors
40
- -----------------
41
-
42
- To register a single custom processor:
43
-
44
- app.processor.add :watermark do |temp_object, *args|
45
- # use temp_object.data, temp_object.path, temp_object.file, etc.
46
- SomeLibrary.add_watermark(temp_object.data, 'some/watermark/file.png')
47
- # return a String, Pathname, File or Tempfile
48
- end
49
-
50
- new_image = image.process(:watermark)
51
-
52
- You can create a class like the ImageMagick one above, in which case all public methods will be counted as processing methods.
53
- Each method takes the temp_object as its argument, plus any other args.
54
-
55
- class MyProcessor
56
-
57
- def coolify(temp_object, opts={})
58
- SomeLib.coolify(temp_object.data, opts)
59
- end
60
-
61
- def uglify(temp_object, ugliness)
62
- `uglify -i #{temp_object.path} -u #{ugliness}`
63
- end
64
-
65
- private
66
-
67
- def my_helper_method
68
- # do stuff
69
- end
70
-
71
- end
72
-
73
- app.processor.register(MyProcessor)
74
-
75
- new_image = image.coolify(:some => :args)
76
-
77
- new_image = image.uglify(:loads)
@@ -1,52 +0,0 @@
1
- Rack
2
- ====
3
- For more info about using Rack applications, see the docs at {http://rack.rubyforge.org/}
4
-
5
- Basic usage involves storing data (e.g. images),
6
- then serving it in some form.
7
-
8
- A basic rackup file `config.ru`:
9
-
10
- require 'rubygems'
11
- require 'dragonfly'
12
-
13
- Dragonfly[:my_app_name].configure do |c|
14
- # ... configuration here
15
- end
16
-
17
- run Dragonfly:App[:my_app_name]
18
-
19
- See {file:Configuration} for more details.
20
-
21
- The basic flow is instantiate an app -> configure it -> run it.
22
-
23
- Example: Using to serve resized images
24
- --------------------------------------
25
-
26
- `config.ru`:
27
-
28
- require 'rubygems'
29
- require 'dragonfly'
30
-
31
- app = Dragonfly[:images].configure_with(:imagemagick)
32
-
33
- run app
34
-
35
- This enables the app to use all the ImageMagick goodies provided by Dragonfly (see {file:Configuration}).
36
- By default the {Dragonfly::DataStorage::FileDataStore file data store} is used.
37
-
38
- In the console:
39
-
40
- app = Dragonfly[:images]
41
-
42
- # Store
43
- uid = app.store(File.new('path/to/image.png')) # ===> unique uid
44
-
45
- # Get the url for a thumbnail
46
- url = app.fetch(uid).thumb('400x300').url # ===> "/media/BAhbBlsHOgZmIg9hc..."
47
-
48
- Now when we visit the url `/media/BAhbBlsHOgZmIg9hc...` in the browser, we get a resized image!
49
-
50
- Mounting in Rack
51
- ----------------
52
- See {file:URLs}
@@ -1,57 +0,0 @@
1
- Using With Rails 2.3
2
- ====================
3
-
4
- **NOTE: RAILS 2.3 IS NOT SUPPORTED IN NEW VERSIONS OF DRAGONFLY SO PLEASE USE VERSION 0.8.5**
5
-
6
- Setting up the quick way
7
- ------------------------
8
- config/initializers/dragonfly.rb:
9
-
10
- require 'dragonfly/rails/images'
11
-
12
- Setting up the more explicit way
13
- --------------------------------
14
- You can do the above explicitly.
15
-
16
- config/initializers/dragonfly.rb:
17
-
18
- require 'dragonfly'
19
-
20
- app = Dragonfly[:images]
21
- app.configure_with(:imagemagick)
22
- app.configure_with(:rails)
23
-
24
- app.define_macro(ActiveRecord::Base, :image_accessor)
25
-
26
- environment.rb:
27
-
28
- config.middleware.insert 0, 'Dragonfly::Middleware', :images, '/media'
29
- config.middleware.insert_before 'Dragonfly::Middleware', 'Rack::Cache', {
30
- :verbose => true,
31
- :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"),
32
- :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
33
- }
34
-
35
- Gems
36
- ----
37
- environment.rb
38
-
39
- config.gem 'dragonfly', '0.8.5'
40
- config.gem 'rack-cache', :lib => 'rack/cache'
41
-
42
- Capistrano
43
- ----------
44
- If using Capistrano with the above, you probably will want to keep the cache between deploys, so in deploy.rb:
45
-
46
- namespace :dragonfly do
47
- desc "Symlink the Rack::Cache files"
48
- task :symlink, :roles => [:app] do
49
- run "mkdir -p #{shared_path}/tmp/dragonfly && ln -nfs #{shared_path}/tmp/dragonfly #{release_path}/tmp/dragonfly"
50
- end
51
- end
52
- after 'deploy:update_code', 'dragonfly:symlink'
53
-
54
- Use it!
55
- -------
56
-
57
- To see what you can do with the model accessors, see {file:Models}.
@@ -1,56 +0,0 @@
1
- Using With Rails 3
2
- ==================
3
-
4
- Setting up the quick way
5
- ------------------------
6
- config/initializers/dragonfly.rb:
7
-
8
- require 'dragonfly/rails/images'
9
-
10
- Setting up the more explicit way
11
- --------------------------------
12
- You can do the above explicitly.
13
-
14
- config/initializers/dragonfly.rb:
15
-
16
- require 'dragonfly'
17
-
18
- app = Dragonfly[:images]
19
- app.configure_with(:imagemagick)
20
- app.configure_with(:rails)
21
-
22
- app.define_macro(ActiveRecord::Base, :image_accessor)
23
-
24
- application.rb:
25
-
26
- config.middleware.insert 0, 'Rack::Cache', {
27
- :verbose => true,
28
- :metastore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"),
29
- :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
30
- } # unless Rails.env.production? ## uncomment this 'unless' in Rails 3.1,
31
- ## because it already inserts Rack::Cache in production
32
-
33
- config.middleware.insert_after 'Rack::Cache', 'Dragonfly::Middleware', :images
34
-
35
- Gemfile
36
- -------
37
-
38
- gem 'dragonfly', '~>0.9.15'
39
- gem 'rack-cache', :require => 'rack/cache'
40
-
41
- Capistrano
42
- ----------
43
- If using Capistrano with the above, you probably will want to keep the cache between deploys, so in deploy.rb:
44
-
45
- namespace :dragonfly do
46
- desc "Symlink the Rack::Cache files"
47
- task :symlink, :roles => [:app] do
48
- run "mkdir -p #{shared_path}/tmp/dragonfly && ln -nfs #{shared_path}/tmp/dragonfly #{release_path}/tmp/dragonfly"
49
- end
50
- end
51
- after 'deploy:update_code', 'dragonfly:symlink'
52
-
53
- Use it!
54
- -------
55
-
56
- To see what you can do with the model accessors, see {file:Models}.
@@ -1,104 +0,0 @@
1
- Serving Content Remotely
2
- ========================
3
-
4
- Dragonfly stores original versions of content in a datastore which could be the {file:DataStorage#File\_datastore filesystem},
5
- {file:DataStorage#S3\_datastore S3}, etc., but when it comes to serving it, or serving a processed version
6
- (e.g. an image thumbnail), it fetches it and serves locally from the {Dragonfly::Server dragonfly server}.
7
-
8
- For most cases, this is the way to go - you have control over it and you can {file:Caching cache it using HTTP caching}.
9
-
10
- However, if for whatever reason you must serve content from the datastore directly, e.g. for lightening the load on your server, Dragonfly
11
- provides a number of ways of doing this.
12
-
13
- Original Content
14
- ----------------
15
- The {file:DataStorage#File\_datastore FileDataStore}, {file:DataStorage#S3\_datastore S3DataStore} and
16
- {file:DataStorage#Couch\_datastore CouchDataStore} allow for serving data directly, so given a Dragonfly app
17
-
18
- app = Dragonfly[:my_app]
19
-
20
- and the uid for some stored content
21
-
22
- uid = app.store(Pathname.new('some/file.jpg'))
23
-
24
- we can get the remote url using
25
-
26
- app.remote_url_for(uid) # e.g. http://my-bucket.s3.amazonaws.com/2011/04/01/03/03/05/243/file.jpg
27
-
28
- or from a model attachment:
29
-
30
- my_model.attachment.remote_url # http://my-bucket.s3.amazonaws.com/2011...
31
-
32
- Processed Content
33
- -----------------
34
- If using models, the quick and easy way to serve e.g. image thumbnails remotely is to process them _on upload_
35
- like most other attachment ruby gems (see {file:Models#Up-front_thumbnailing}),
36
- e.g. for my avatar model,
37
-
38
- class Avatar
39
- image_accessor :image do
40
- copy_to(:small_image){|a| a.thumb('200x200#') }
41
- end
42
- image_accessor :small_image
43
- end
44
-
45
- Then we can use `remote_url` for for each accessor.
46
-
47
- avatar.image.remote_url # http://my-bucket.s3.amazonaws.com/some/path.jpg
48
- avatar.small_image.remote_url # http://my-bucket.s3.amazonaws.com/some/other/path.jpg
49
-
50
- However, this has all the limitations that come with up-front processing, such as having to regenerate the thumbnail when the size requirement changes.
51
-
52
- Serving Processed Content *on-the-fly*
53
- --------------------------------------
54
- Serving processed versions of content such as thumbnails remotely is a bit more tricky as we need to upload the thumbnail
55
- to the datastore in the on-the-fly manner.
56
-
57
- Dragonfly provides a way of doing this using `define_url` and `before_serve` methods.
58
-
59
- The details of keeping track of/expiring these thumbnails is up to you.
60
-
61
- We need to keep track of which thumbnails have been already created, by storing a uid for each one.
62
- Below is an example using an ActiveRecord 'Thumb' table to keep track of already created thumbnail uids.
63
- It has two string columns; 'job' and 'uid'.
64
-
65
- app.configure do |c|
66
-
67
- # Override the .url method...
68
- c.define_url do |app, job, opts|
69
- thumb = Thumb.find_by_job(job.serialize)
70
- # If (fetch 'some_uid' then resize to '40x40') has been stored already, give the datastore's remote url ...
71
- if thumb
72
- app.datastore.url_for(thumb.uid)
73
- # ...otherwise give the local Dragonfly server url
74
- else
75
- app.server.url_for(job)
76
- end
77
- end
78
-
79
- # Before serving from the local Dragonfly server...
80
- c.server.before_serve do |job, env|
81
- # ...store the thumbnail in the datastore...
82
- uid = job.store
83
-
84
- # ...keep track of its uid so next time we can serve directly from the datastore
85
- Thumb.create!(
86
- :uid => uid,
87
- :job => job.serialize # 'BAhbBls...' - holds all the job info
88
- ) # e.g. fetch 'some_uid' then resize to '40x40'
89
- end
90
-
91
- end
92
-
93
- This would give
94
-
95
- app.fetch('some_uid').thumb('40x40').url # normal Dragonfly url e.g. /media/BAhbBls...
96
-
97
- then from the second time onwards
98
-
99
- app.fetch('some_uid').thumb('40x40').url # http://my-bucket.s3.amazonaws.com/2011...
100
-
101
- The above is just an example - there are a number of things you could do with `before_serve` and `define_url` -
102
- you could use e.g. Redis or some key-value store to keep track of thumbnails.
103
- You'd also probably want a way of expiring the thumbnails or destroying them when the original is destroyed, but this
104
- is left up to you as it's outside of the scope of Dragonfly.
@@ -1,25 +0,0 @@
1
- Sinatra
2
- =======
3
- You can use {Dragonfly::Job Job}'s `to_response` method like so:
4
-
5
- app = Dragonfly[:images].configure_with(:imagemagick)
6
-
7
- get '/images/:size.:format' do |size, format|
8
- app.fetch_file('~/some/image.png').thumb(size).encode(format).to_response(env)
9
- end
10
-
11
- `to_response` returns a rack-style response array with status, headers and body.
12
-
13
- NOTE: uids from the datastore may have slashes and dots in them so make sure you escape url-escape them when using ':uid' as
14
- a path segment.
15
-
16
- or you can mount as a middleware, like in rails:
17
-
18
- Dragonfly[:images].configure_with(:imagemagick) do |c|
19
- c.url_format = '/media/:job'
20
- end
21
-
22
- use Dragonfly::Middleware, :images
23
-
24
- get '/' #... do
25
- # ...
@@ -1,203 +0,0 @@
1
- URLs
2
- ====
3
-
4
- We can get urls for any kind of job:
5
-
6
- app = Dragonfly[:images]
7
-
8
- app.fetch('my_uid').process(:flip).url # "/BAhbBlsH..."
9
- app.generate(:text, 'hello').thumb('500x302').gif.url # "/BAhbCFsHOgZ..."
10
-
11
- Path format
12
- -----------
13
- The format of the standard urls can be configured using `url_format`:
14
-
15
- app.configure do |c|
16
- c.url_format = '/:job'
17
- end
18
-
19
- (or call `app.server.url_format=` directly).
20
-
21
- `url_format = '/:job/:basename.:format'`:
22
-
23
- media = app.fetch('my_uid')
24
- media.url # "/BAhbBlsHOgZmSSIJbWlsawY6BkVU"
25
- media.name = 'milk.txt'
26
- media.url # "/BAhbBlsHOgZmSSIJbWlsawY6BkVU/milk.txt"
27
- media.encode(:pdf).url # "/BAhbB1sHOgZ...RbBzoGZToIcGRm/milk.pdf"
28
- media.url(:format => 'bang') # "/BAhbBlsHOgZmSSIJbWlsawY6BkVU/milk.bang"
29
- media.url(:some => 'thing') # "/BAhbBlsHOgZmSSIJbWlsawY6BkVU/milk.txt?some=thing"
30
-
31
- `url_format = '/some-prefix/:job'`:
32
-
33
- media = app.fetch('my_uid')
34
- media.url # "/some-prefix/BAhbBlsHOgZmSSIJbWlsawY6BkVU"
35
-
36
- `url_format = '/blah'`:
37
-
38
- media = app.fetch('my_uid')
39
- media.url # "/blah?job=BAhbBlsHOgZmSSIJbWlsawY6BkVU"
40
-
41
- When using {file:Models}, any {file:Models#_Magic__Attributes magic attributes} will be used in url generation, e.g.
42
-
43
- app.server.url_format = '/frogs/:job/:basename-:width.:format'
44
-
45
- with
46
-
47
- class Frog
48
- image_accessor :face # columns face_uid, face_name and face_width
49
- end
50
-
51
- gives
52
-
53
- frog = Frog.new :face => Pathname.new('froggie.jpg') # image with width 400
54
-
55
- frog.face.url # "/frogs/BAhbBlsHOgZmSSIIc2RmBjoGRVQ/froggie-400.jpg"
56
-
57
- Host
58
- ----
59
- You can also set a host for the urls
60
-
61
- app.configure{|c| c.url_host = 'http://some.host' } # or directly on app.server
62
-
63
- app.fetch('my_uid').url # "http://some.host/BAhb..."
64
-
65
- app.fetch('my_uid').url(:host => 'http://localhost:80') # "http://localhost:80/BAh..."
66
-
67
- Content-Disposition
68
- -------------------
69
- You can manually set the content-disposition of the response:
70
-
71
- app.content_disposition = :attachment # should be :inline or :attachment (or :hidden)
72
-
73
- `:attachment` tells the browser to download it, `:inline` tells it to display in-browser if possible.
74
-
75
- You can also use a block:
76
-
77
- app.content_disposition = proc{|job, request|
78
- if job.format == :jpg || request['d'] == 'inline' # request is a Rack::Request object
79
- :inline
80
- else
81
- :attachment
82
- end
83
- }
84
-
85
- Downloaded filename
86
- -------------------
87
- To specify the filename the browser uses for 'Save As' dialogues:
88
-
89
- app.content_filename = proc{|job, request|
90
- if job.process_steps.any?
91
- "#{job.basename}_#{job.process_steps.first.name}.#{job.format}"
92
- else
93
- "#{job.basename}.#{job.format}"
94
- end
95
- }
96
-
97
- This will for example give the following filenames for the following jobs:
98
-
99
- app.fetch('some/tree.png') # -> 'tree.png'
100
- app.fetch('some/tree.png').process(:greyscale) # -> 'tree_greyscale.png'
101
- app.fetch('some/tree.png').process(:greyscale).gif # -> 'tree_greyscale.gif'
102
-
103
- By default the original filename is used, with a modified extension if it's been encoded.
104
-
105
- Routed Endpoints
106
- ----------------
107
- You can also use a number of Rack-based routers and create Dragonfly endpoints.
108
-
109
- If we have an app set up for using ImageMagick:
110
-
111
- app = Dragonfly[:images].configure_with(:imagemagick)
112
-
113
- Then to get the url '/text/hello' to display the text "hello"...
114
-
115
- Rails 3 (routes.rb):
116
-
117
- match '/text/:text' => app.endpoint { |params, app|
118
- app.generate(:text, params[:text])
119
- }
120
-
121
- {http://github.com/josh/rack-mount Rack-Mount}:
122
-
123
- Routes = Rack::Mount::RouteSet.new do |set|
124
-
125
- set.add_route app.endpoint{|params, a| a.generate(:text, params[:text]) },
126
- :path_info => %r{/text/(?:<text>.+)}
127
-
128
- # ...
129
-
130
- end
131
-
132
- {http://github.com/joshbuddy/usher Usher}:
133
-
134
- routes = Usher::Interface.for(:rack) do
135
- add('/text/:text').to app.endpoint { |params, app|
136
- app.generate(:text, params[:text])
137
- }
138
- end
139
-
140
- {http://github.com/joshbuddy/http_router HTTP Router}:
141
-
142
- r = HttpRouter.new
143
- r.add('/text/:text').to app.endpoint { |params, app|
144
- app.generate(:text, params[:text])
145
- }
146
-
147
- In each case the url will need to be generated by the router of choice, or manually.
148
-
149
- NOTE: Ruby treats curly braces slightly differently to `do`...`end` so be aware of this when using the above examples.
150
-
151
- Simple Endpoints
152
- ----------------
153
- {Dragonfly::Job Job} objects can also be turned straight into Rack endpoints using `to_app`, e.g. in Rails 3:
154
-
155
- match '/beach' => app.fetch_file('~/some/image.png').thumb('100x100#').jpg.to_app
156
-
157
-
158
- Denial-of-service attacks
159
- -------------------------
160
- Although the standard urls are fairly cryptic, a malicious person who knows the Dragonfly source code could potentially
161
- work out how to generate urls to spam your server with heavy requests, e.g. resize to 100000 by 100000 pixels.
162
-
163
- Therefore the app can be protected by requiring the presence of a "DOS-protection" SHA in the urls:
164
-
165
- app.configure do |c|
166
- c.protect_from_dos_attacks = true
167
- c.secret = 'You should supply some random secret here'
168
- end
169
-
170
- Then the standard generated urls will have a SHA query parameter attached:
171
-
172
- app.fetch('my_uid').url # "/BAhbBlsHOgZmIghzZGY?s=df76ba27"
173
-
174
- Any requests without the correct SHA parameter result in a 400 (bad parameters) error response.
175
-
176
- You can also validate for a correct SHA using routed endpoints:
177
-
178
- match '/text/:text' => app.endpoint{|params, app|
179
- app.generate(:text, params[:text]).validate_sha!(params[:sha])
180
- }
181
-
182
- ... where obviously you need to pass in a 'sha' parameter to the url, which can be found using
183
-
184
- app.generate(:text, 'some text').sha
185
-
186
- Overriding responses
187
- --------------------
188
- You can override/add headers using `response_headers`:
189
-
190
- app.configure do |c|
191
- c.response_headers['X-Something'] = 'Custom header' # set directly..
192
- c.response_headers['summink'] = proc{|job, request| # ...or via a callback
193
- job.image? ? 'image yo' : 'not an image'
194
- }
195
- end
196
-
197
- You can intercept the response from the dragonfly server by throwing `:halt` with a Rack response array from inside the `before_serve` callback:
198
-
199
- app.configure do |c|
200
- c.server.before_serve do |job, env|
201
- throw :halt, [200, {'Content-type' => 'text/plain'}, ['hello']]
202
- end
203
- end