dragonfly 0.6.2 → 0.7.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 (157) hide show
  1. data/.gitignore +2 -0
  2. data/.specopts +2 -0
  3. data/.yardopts +11 -5
  4. data/Gemfile +22 -0
  5. data/Gemfile.rails.2.3.5 +13 -0
  6. data/History.md +49 -0
  7. data/README.md +18 -28
  8. data/Rakefile +24 -36
  9. data/VERSION +1 -1
  10. data/config.ru +4 -1
  11. data/dragonfly.gemspec +85 -99
  12. data/extra_docs/Analysers.md +66 -30
  13. data/extra_docs/Caching.md +22 -0
  14. data/extra_docs/Configuration.md +116 -0
  15. data/extra_docs/DataStorage.md +114 -14
  16. data/extra_docs/Encoding.md +62 -37
  17. data/extra_docs/GeneralUsage.md +118 -0
  18. data/extra_docs/Generators.md +92 -0
  19. data/extra_docs/Heroku.md +51 -0
  20. data/extra_docs/Index.md +8 -9
  21. data/extra_docs/MimeTypes.md +18 -17
  22. data/extra_docs/Models.md +251 -0
  23. data/extra_docs/Processing.md +94 -70
  24. data/extra_docs/Rack.md +53 -0
  25. data/extra_docs/Rails2.md +44 -0
  26. data/extra_docs/Rails3.md +51 -0
  27. data/extra_docs/Sinatra.md +21 -0
  28. data/extra_docs/URLs.md +114 -0
  29. data/features/images.feature +6 -7
  30. data/features/no_processing.feature +0 -6
  31. data/features/rails_2.3.5.feature +1 -1
  32. data/features/rails_3.0.0.rc.feature +8 -0
  33. data/features/steps/dragonfly_steps.rb +14 -12
  34. data/features/steps/rails_steps.rb +20 -9
  35. data/features/support/env.rb +10 -11
  36. data/fixtures/files/app/views/albums/new.html.erb +4 -4
  37. data/fixtures/files/app/views/albums/show.html.erb +1 -1
  38. data/fixtures/files/features/manage_album_images.feature +1 -1
  39. data/fixtures/files/features/step_definitions/{album_steps.rb → image_steps.rb} +4 -3
  40. data/fixtures/files/features/support/paths.rb +2 -0
  41. data/fixtures/files/features/text_images.feature +7 -0
  42. data/fixtures/rails_3.0.0.rc/template.rb +21 -0
  43. data/irbrc.rb +2 -1
  44. data/lib/dragonfly.rb +4 -16
  45. data/lib/dragonfly/{active_record_extensions.rb → active_model_extensions.rb} +1 -1
  46. data/lib/dragonfly/active_model_extensions/attachment.rb +146 -0
  47. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/class_methods.rb +5 -6
  48. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/instance_methods.rb +1 -1
  49. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/validations.rb +5 -9
  50. data/lib/dragonfly/analyser.rb +59 -0
  51. data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
  52. data/lib/dragonfly/analysis/r_magick_analyser.rb +46 -31
  53. data/lib/dragonfly/app.rb +138 -173
  54. data/lib/dragonfly/config/heroku.rb +19 -0
  55. data/lib/dragonfly/config/r_magick.rb +37 -0
  56. data/lib/dragonfly/config/{rails_defaults.rb → rails.rb} +6 -7
  57. data/lib/dragonfly/configurable.rb +30 -27
  58. data/lib/dragonfly/core_ext/object.rb +1 -1
  59. data/lib/dragonfly/data_storage/file_data_store.rb +59 -26
  60. data/lib/dragonfly/data_storage/mongo_data_store.rb +65 -0
  61. data/lib/dragonfly/data_storage/s3data_store.rb +31 -12
  62. data/lib/dragonfly/encoder.rb +13 -0
  63. data/lib/dragonfly/encoding/r_magick_encoder.rb +10 -19
  64. data/lib/dragonfly/endpoint.rb +43 -0
  65. data/lib/dragonfly/function_manager.rb +65 -0
  66. data/lib/dragonfly/{processing/r_magick_text_processor.rb → generation/r_magick_generator.rb} +25 -11
  67. data/lib/dragonfly/generator.rb +9 -0
  68. data/lib/dragonfly/job.rb +290 -0
  69. data/lib/dragonfly/job_builder.rb +39 -0
  70. data/lib/dragonfly/job_definitions.rb +26 -0
  71. data/lib/dragonfly/job_endpoint.rb +17 -0
  72. data/lib/dragonfly/loggable.rb +28 -0
  73. data/lib/dragonfly/middleware.rb +21 -14
  74. data/lib/dragonfly/processing/r_magick_processor.rb +71 -48
  75. data/lib/dragonfly/processor.rb +9 -0
  76. data/lib/dragonfly/r_magick_utils.rb +24 -0
  77. data/lib/dragonfly/rails/images.rb +10 -7
  78. data/lib/dragonfly/routed_endpoint.rb +42 -0
  79. data/lib/dragonfly/serializer.rb +32 -0
  80. data/lib/dragonfly/simple_cache.rb +23 -0
  81. data/lib/dragonfly/simple_endpoint.rb +64 -0
  82. data/lib/dragonfly/temp_object.rb +77 -45
  83. data/spec/argument_matchers.rb +7 -17
  84. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
  85. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
  86. data/spec/dragonfly/{active_record_extensions → active_model_extensions}/model_spec.rb +282 -244
  87. data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
  88. data/spec/dragonfly/analyser_spec.rb +123 -0
  89. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +2 -2
  90. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +10 -1
  91. data/spec/dragonfly/app_spec.rb +175 -69
  92. data/spec/dragonfly/configurable_spec.rb +14 -0
  93. data/spec/dragonfly/data_storage/data_store_spec.rb +36 -9
  94. data/spec/dragonfly/data_storage/file_data_store_spec.rb +61 -38
  95. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +18 -0
  96. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +34 -39
  97. data/spec/dragonfly/deprecation_spec.rb +20 -0
  98. data/spec/dragonfly/function_manager_spec.rb +154 -0
  99. data/spec/dragonfly/generation/r_magick_generator_spec.rb +119 -0
  100. data/spec/dragonfly/job_builder_spec.rb +37 -0
  101. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  102. data/spec/dragonfly/job_endpoint_spec.rb +66 -0
  103. data/spec/dragonfly/job_spec.rb +605 -0
  104. data/spec/dragonfly/loggable_spec.rb +80 -0
  105. data/spec/dragonfly/middleware_spec.rb +37 -17
  106. data/spec/dragonfly/processing/r_magick_processor_spec.rb +182 -166
  107. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  108. data/spec/dragonfly/serializer_spec.rb +61 -0
  109. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  110. data/spec/dragonfly/simple_endpoint_spec.rb +78 -0
  111. data/spec/dragonfly/temp_object_spec.rb +154 -119
  112. data/spec/simple_matchers.rb +22 -0
  113. data/spec/spec_helper.rb +28 -4
  114. data/yard/templates/default/layout/html/layout.erb +18 -11
  115. metadata +89 -190
  116. data/config.rb +0 -5
  117. data/extra_docs/ActiveRecord.md +0 -196
  118. data/extra_docs/ExampleUseCases.md +0 -189
  119. data/extra_docs/GettingStarted.md +0 -114
  120. data/extra_docs/Shortcuts.md +0 -118
  121. data/extra_docs/UsingWithRails.md +0 -81
  122. data/features/rails_3.0.0.beta3.feature +0 -7
  123. data/fixtures/rails_3.0.0.beta3/template.rb +0 -16
  124. data/lib/dragonfly/active_record_extensions/attachment.rb +0 -170
  125. data/lib/dragonfly/analyser_list.rb +0 -9
  126. data/lib/dragonfly/analysis/base.rb +0 -10
  127. data/lib/dragonfly/belongs_to_app.rb +0 -24
  128. data/lib/dragonfly/config/heroku_rails_images.rb +0 -23
  129. data/lib/dragonfly/config/r_magick_images.rb +0 -69
  130. data/lib/dragonfly/config/r_magick_text.rb +0 -25
  131. data/lib/dragonfly/config/rails_images.rb +0 -13
  132. data/lib/dragonfly/data_storage/base.rb +0 -21
  133. data/lib/dragonfly/data_storage/base64_data_store.rb +0 -23
  134. data/lib/dragonfly/data_storage/transparent_data_store.rb +0 -21
  135. data/lib/dragonfly/delegatable.rb +0 -14
  136. data/lib/dragonfly/delegator.rb +0 -62
  137. data/lib/dragonfly/encoder_list.rb +0 -9
  138. data/lib/dragonfly/encoding/base.rb +0 -14
  139. data/lib/dragonfly/encoding/transparent_encoder.rb +0 -14
  140. data/lib/dragonfly/extended_temp_object.rb +0 -120
  141. data/lib/dragonfly/parameters.rb +0 -163
  142. data/lib/dragonfly/processing/base.rb +0 -10
  143. data/lib/dragonfly/processor_list.rb +0 -9
  144. data/lib/dragonfly/url_handler.rb +0 -147
  145. data/spec/dragonfly/active_record_extensions/attachment_spec.rb +0 -8
  146. data/spec/dragonfly/active_record_extensions/migration.rb +0 -42
  147. data/spec/dragonfly/active_record_extensions/models.rb +0 -6
  148. data/spec/dragonfly/active_record_extensions/spec_helper.rb +0 -24
  149. data/spec/dragonfly/belongs_to_app_spec.rb +0 -55
  150. data/spec/dragonfly/delegatable_spec.rb +0 -32
  151. data/spec/dragonfly/delegator_spec.rb +0 -145
  152. data/spec/dragonfly/extended_temp_object_spec.rb +0 -71
  153. data/spec/dragonfly/parameters_spec.rb +0 -298
  154. data/spec/dragonfly/processing/r_magick_text_processor_spec.rb +0 -84
  155. data/spec/dragonfly/url_handler_spec.rb +0 -247
  156. data/spec/dragonfly_spec.rb +0 -16
  157. data/spec/ginger_scenarios.rb +0 -13
@@ -1,98 +1,122 @@
1
1
  Processing
2
2
  ==========
3
3
 
4
- Processing is changing content in some way, and does not involve encoding.
5
- For example, resizing an image is classed as processing, whereas converting it from 'png' to 'jpeg' is classed as encoding.
4
+ Changing data in some way, e.g. resizing an image, comes under the banner of Processing.
6
5
 
7
- All processing jobs are defined by a processing method and a processing options hash (which is passed to the method).
6
+ You can register as many processors as you like.
8
7
 
9
- Let's say we have a dragonfly app called 'images'
8
+ Let's say we have a Dragonfly app
10
9
 
11
- app = Dragonfly::App[:images]
10
+ app = Dragonfly[:images]
12
11
 
13
- Data gets passed around between the datastore, processor, analyser, etc. in the form of an {Dragonfly::ExtendedTempObject ExtendedTempObject}.
12
+ and an image object (actually a {Dragonfly::Job Job} object)...
14
13
 
15
- temp_object = app.create_object(File.new('path/to/image.png'))
14
+ image = app.fetch('some/uid')
16
15
 
17
- We can process this object with any of the methods which have been registered with the app's processor.
18
- For example, registering the {Dragonfly::Processing::RMagickProcessor rmagick processor}
16
+ ...OR a Dragonfly model accessor...
19
17
 
20
- app.register_processor(Dragonfly::Processing::RMagickProcessor)
18
+ image = @album.cover_image
21
19
 
22
- give us the processing methods `resize`, `crop`, `resize_and_crop`, `rotate`, etc.
20
+ We can process it using any processing methods that have been registered with the processor.
23
21
 
24
- temp_object.process(:resize, :geometry => '30x30!') # => returns a new temp_object with width x height = 30x30
25
- temp_object.process!(:resize, :geometry => '30x30!') # => resizes its own data
22
+ RMagickProcessor
23
+ ----------------
24
+ The {Dragonfly::Processing::RMagickProcessor RMagickProcessor} is registered by default by
25
+ the {Dragonfly::Config::RMagick RMagick configuration} used by 'dragonfly/rails/images'.
26
26
 
27
- The saved configuration {Dragonfly::Config::RMagickImages RMagickImages} registers the above processor automatically.
27
+ If not already registered:
28
28
 
29
- Custom Processing
30
- -----------------
29
+ app.processor.register(Dragonfly::Processing::RMagickProcessor)
31
30
 
32
- To register a custom processor, derive from {Dragonfly::Processing::Base Processing::Base} and register.
33
- Each method takes the temp_object, and the (optional) processing options hash as its argument.
31
+ gives us these methods:
34
32
 
35
- class MyProcessor < Dragonfly::Processing::Base
36
-
37
- def black_and_white(temp_object, opts={})
38
- # use temp_object.data, temp_object.path, etc...
39
- # ...process and return a String, File, Tempfile or TempObject
40
- end
33
+ image.process(:thumb, '400x300#') # see below
41
34
 
42
- # ... add as many methods as you wish
35
+ image.process(:crop, :width => 40, :height => 50, :x => 20, :y => 30)
36
+ image.process(:crop, :width => 40, :height => 50, :gravity => 'ne')
43
37
 
44
- end
38
+ image.process(:flip) # flips it vertically
39
+ image.process(:flop) # flips it horizontally
45
40
 
46
- app = Dragonfly::App[:images]
47
- app.register_processor(MyProcessor)
41
+ image.process(:greyscale, :depth => 128) # default depth 256
48
42
 
49
- You can register multiple processors.
43
+ image.process(:resize, '40x40')
44
+ image.process(:resize_and_crop, :width => 40, :height=> 50, :gravity => 'ne')
50
45
 
51
- As with analysers and encoders, if the processor is {Dragonfly::Configurable configurable}, we can configure it as we register it if we need to
46
+ image.process(:rotate, 45, :background_colour => 'transparent') # default bg black
52
47
 
53
- app.register_processor(MyProcessor) do |p|
54
- p.some_attribute = 'hello'
55
- end
48
+ image.process(:vignette) # options :x, :y, :radius, :sigma
49
+
50
+ The method `thumb` takes a geometry string and calls `resize`, `resize_and_crop` or `crop` accordingly.
51
+
52
+ image.process(:thumb, '400x300') # calls resize
53
+
54
+ Below are some examples of geometry strings:
55
+
56
+ '400x300' # resize, maintain aspect ratio
57
+ '400x300!' # force resize, don't maintain aspect ratio
58
+ '400x' # resize width, maintain aspect ratio
59
+ 'x300' # resize height, maintain aspect ratio
60
+ '400x300>' # resize only if the image is larger than this
61
+ '400x300<' # resize only if the image is smaller than this
62
+ '50x50%' # resize width and height to 50%
63
+ '400x300^' # resize width, height to minimum 400,300, maintain aspect ratio
64
+ '2000@' # resize so max area in pixels is 2000
65
+ '400x300#' # resize, crop if necessary to maintain aspect ratio (centre gravity)
66
+ '400x300#ne' # as above, north-east gravity
67
+ '400x300se' # crop, with south-east gravity
68
+ '400x300+50+100' # crop from the point 50,100 with width, height 400,300
69
+
70
+ Lazy evaluation
71
+ ---------------
72
+
73
+ new_image = image.process(:some_method)
74
+
75
+ doesn't actually do anything until you call something on the returned {Dragonfly::Job Job} object, like `url`, `data`, etc.
76
+
77
+ Bang method
78
+ -----------
79
+
80
+ image.process!(:some_method)
81
+
82
+ modifies the image object itself, rather than returning a new object.
56
83
 
57
- Your new processing method is now available to use:
58
-
59
- temp_object = app.create_object(File.new('path/to/image.png'))
60
- temp_object.process(:black_and_white, :some => 'option') # processed temp_object
61
-
62
- To get the url for content processed by your custom processor, the long way is using something like:
63
-
64
- app.url_for('some_uid',
65
- :processing_method => :black_and_white,
66
- :processing_options => {:size => '30x30'},
67
- :format => :png
68
- )
69
-
70
- or if using an activerecord model,
71
-
72
- my_model.preview_image.url('some_uid',
73
- :processing_method => :black_and_white,
74
- :processing_options => {:size => '30x30'},
75
- :format => :png
76
- )
77
-
78
- However, this could soon get tedious if using more than once, so the best thing is to register a shortcut for it.
79
- So in your configuration of the Dragonfly app (or in an initializer if using 'dragonfly/rails/images') you
80
- could do something like:
81
-
82
- app.parameters.add_shortcut(/^bw-(\d*x\d*)$/) do |string, match_data|
83
- {
84
- :processing_method => :black_and_white,
85
- :processing_options => {:size => match_data[1]},
86
- :format => :png
87
- }
84
+ Custom Processors
85
+ -----------------
86
+
87
+ To register a single custom processor:
88
+
89
+ app.processor.add :watermark do |temp_object, *args|
90
+ # use temp_object.data, temp_object.path, temp_object.file, etc.
91
+ SomeLibrary.add_watermark(temp_object.data, 'some/watermark/file.png')
92
+ # return a String, File or Tempfile
88
93
  end
89
-
90
- Now you can get urls by using the shortcut:
91
94
 
92
- app.url_for('some_uid', 'bw-30x30')
95
+ new_image = image.process(:watermark)
96
+
97
+ You can create a class like the RMagick one above, in which case all public methods will be counted as processing methods.
98
+ Each method takes the temp_object as its argument, plus any other args.
99
+
100
+ class MyProcessor
101
+
102
+ def coolify(temp_object, opts={})
103
+ SomeLib.coolify(temp_object.data, opts)
104
+ end
105
+
106
+ def uglify(temp_object, ugliness)
107
+ `uglify -i #{temp_object.path} -u #{ugliness}`
108
+ end
109
+
110
+ private
111
+
112
+ def my_helper_method
113
+ # do stuff
114
+ end
115
+
116
+ end
93
117
 
94
- or with activerecord:
118
+ app.processor.register(MyProcessor)
95
119
 
96
- my_model.preview_image.url('bw-30x30')
120
+ new_image = image.coolify(:some => :args)
97
121
 
98
- For more information about shortcuts, see {file:Shortcuts}.
122
+ new_image = image.uglify(:loads)
@@ -0,0 +1,53 @@
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]
32
+ app.configure_with(:rmagick)
33
+
34
+ run app
35
+
36
+ This enables the app to use all the RMagick goodies provided by Dragonfly (see {file:Configuration}).
37
+ By default the {Dragonfly::DataStorage::FileDataStore file data store} is used.
38
+
39
+ In the console:
40
+
41
+ app = Dragonfly[:images]
42
+
43
+ # Store
44
+ uid = app.store(File.new('path/to/image.png')) # ===> unique uid
45
+
46
+ # Get the url for a thumbnail
47
+ url = app.fetch(uid).thumb('400x300').url # ===> "/media/BAhbBlsHOgZmIg9hc..."
48
+
49
+ Now when we visit the url `/media/BAhbBlsHOgZmIg9hc...` in the browser, we get a resized image!
50
+
51
+ Mounting in Rack
52
+ ----------------
53
+ See {file:URLs}
@@ -0,0 +1,44 @@
1
+ Using With Rails 2.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(:rmagick)
20
+ app.configure_with(:rails)
21
+
22
+ app.define_macro(ActiveRecord::Base, :image_accessor)
23
+
24
+ environment.rb:
25
+
26
+ config.middleware.insert 0, 'Dragonfly::Middleware', :images, '/media'
27
+ config.middleware.insert 0, 'Rack::Cache', {
28
+ :verbose => true,
29
+ :metastore => "file:#{Rails.root}/tmp/dragonfly/cache/meta",
30
+ :entitystore => "file:#{Rails.root}/tmp/dragonfly/cache/body"
31
+ }
32
+
33
+ Gems
34
+ ----
35
+ environment.rb
36
+
37
+ config.gem 'dragonfly', '~>0.7.0'
38
+ config.gem 'rmagick', :lib => 'RMagick'
39
+ config.gem 'rack-cache', :lib => 'rack/cache'
40
+
41
+ Use it!
42
+ -------
43
+
44
+ To see what you can do with the model accessors, see {file:Models}.
@@ -0,0 +1,51 @@
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(:rmagick)
20
+ app.configure_with(:rails)
21
+
22
+ app.define_macro(ActiveRecord::Base, :image_accessor)
23
+
24
+ application.rb:
25
+
26
+ config.middleware.insert 0, 'Dragonfly::Middleware', :images, '/media'
27
+ config.middleware.insert 0, 'Rack::Cache', {
28
+ :verbose => true,
29
+ :metastore => "file:#{Rails.root}/tmp/dragonfly/cache/meta",
30
+ :entitystore => "file:#{Rails.root}/tmp/dragonfly/cache/body"
31
+ }
32
+
33
+ Gemfile
34
+ -------
35
+
36
+ gem 'dragonfly', '~>0.7.0'
37
+ gem 'rmagick', :require => 'RMagick'
38
+ gem 'rack-cache', :require => 'rack/cache'
39
+
40
+ Use it!
41
+ -------
42
+
43
+ To see what you can do with the model accessors, see {file:Models}.
44
+
45
+ Mounting in routes.rb
46
+ ---------------------
47
+ Instead of mounting as a middleware, you could skip that bit and mount directly in the routes.rb file:
48
+
49
+ match '/media(/:dragonfly)', :to => Dragonfly[:images]
50
+
51
+ Make sure the the path prefix matches the Dragonfly app's configured url_path_prefix (which is /media by default for Rails).
@@ -0,0 +1,21 @@
1
+ Sinatra
2
+ =======
3
+ You can use {Dragonfly::Job Job}'s `to_response` method like so:
4
+
5
+ get '/images/:size.:format' do |size, format|
6
+ app.fetch_file('~/some/image.png').thumb(size).encode(format).to_response
7
+ end
8
+
9
+ NOTE: uids from the datastore currently have slashes and dots in them so may cause problems when using ':uid' as
10
+ a path segment.
11
+
12
+ or you can mount as a middleware, like in rails:
13
+
14
+ Dragonfly[:images].configure_with(:rmagick) do |c|
15
+ c.url_path_prefix = '/media'
16
+ end
17
+
18
+ use Dragonfly::Middleware, :images, '/media'
19
+
20
+ get '/' #... do
21
+ # ...
@@ -0,0 +1,114 @@
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 prefix
12
+ -----------
13
+ If the app is mounted with a path prefix (such as when using in Rails), then we need to add this prefix
14
+ to the urls:
15
+
16
+ app.url_path_prefix = '/media'
17
+
18
+ (or done in a configuration block).
19
+
20
+ app.fetch('my_uid').url # "/media/BAhbBlsH..."
21
+
22
+ This is done for you when using {file:Configuration Rails defaults}.
23
+
24
+ You can override it using
25
+
26
+ app.fetch('my_uid').url(:path_prefix => '/images') # "/images/BAhbBlsH..."
27
+
28
+ Host
29
+ ----
30
+ You can also set a host for the urls
31
+
32
+ app.url_host = 'http://some.host'
33
+ app.fetch('my_uid').url # "http://some.host/BAhb..."
34
+
35
+ app.fetch('my_uid').url(:host => 'http://localhost:80') # "http://localhost:80/BAh..."
36
+
37
+ Routed Endpoints
38
+ ----------------
39
+ You can also use a number of Rack-based routers and create Dragonfly endpoints.
40
+
41
+ If we have an app set up for using RMagick:
42
+
43
+ app = Dragonfly[:images].configure_with(:rmagick)
44
+
45
+ Then to get the url '/text/hello' to display the text "hello"...
46
+
47
+ Rails 3 (routes.rb):
48
+
49
+ match '/text/:text' => app.endpoint{|params, app|
50
+ app.generate(:text, params[:text])
51
+ }
52
+
53
+ {http://github.com/josh/rack-mount Rack-Mount}:
54
+
55
+ Routes = Rack::Mount::RouteSet.new do |set|
56
+
57
+ set.add_route app.endpoint{|params, a| a.generate(:text, params[:text]) },
58
+ :path_info => %r{/text/(?:<text>.+)}
59
+
60
+ # ...
61
+
62
+ end
63
+
64
+ {http://github.com/joshbuddy/usher Usher}:
65
+
66
+ routes = Usher::Interface.for(:rack) do
67
+ add('/text/:text').to app.endpoint{|params, app|
68
+ app.generate(:text, params[:text])
69
+ }
70
+ end
71
+
72
+ {http://github.com/joshbuddy/http_router HTTP Router}:
73
+
74
+ r = HttpRouter.new
75
+ r.add('/text/:text').to app.endpoint{|params, app|
76
+ app.generate(:text, params[:text])
77
+ }
78
+
79
+ In each case the url will need to be generated by the router of choice, or manually.
80
+
81
+ Simple Endpoints
82
+ ----------------
83
+ {Dragonfly::Job Job} objects can also be turned straight into Rack endpoints using `to_app`, e.g. in Rails 3:
84
+
85
+ match '/beach' => app.fetch_file('~/some/image.png').thumb('100x100#').jpg.to_app
86
+
87
+
88
+ Denial-of-service attacks
89
+ -------------------------
90
+ Although the standard urls are fairly cryptic, a malicious person who knows the Dragonfly source code could potentially
91
+ work out how to generate urls to spam your server with heavy requests, e.g. resize to 100000 by 100000 pixels.
92
+
93
+ Therefore the app can be protected by requiring the presence of a "DOS-protection" SHA in the urls:
94
+
95
+ app.configure do |c|
96
+ c.protect_from_dos_attacks = true
97
+ c.secret = 'You should supply some random secret here'
98
+ end
99
+
100
+ Then the standard generated urls will have a SHA query parameter attached:
101
+
102
+ app.fetch('my_uid').url # "/BAhbBlsHOgZmIghzZGY?s=df76ba27"
103
+
104
+ Any requests without the correct SHA parameter result in a 400 (bad parameters) error response.
105
+
106
+ You can also validate for a correct SHA using routed endpoints:
107
+
108
+ match '/text/:text' => app.endpoint{|params, app|
109
+ app.generate(:text, params[:text]).validate_sha!(params[:sha])
110
+ }
111
+
112
+ ... where obviously you need to pass in a 'sha' parameter to the url, which can be found using
113
+
114
+ app.generate(:text, 'some text').sha