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
data/config.rb DELETED
@@ -1,5 +0,0 @@
1
- require File.dirname(__FILE__) + '/lib/dragonfly'
2
-
3
- APP = Dragonfly::App[:images]
4
- APP.configure_with(Dragonfly::Config::RMagickImages)
5
- APP.url_handler.protect_from_dos_attacks = false
@@ -1,196 +0,0 @@
1
- ActiveRecord Extensions
2
- =======================
3
-
4
- Dragonfly provides a module that extends ActiveRecord so that you can access Dragonfly objects as if they were just another model attribute.
5
-
6
- Registering with ActiveRecord
7
- -----------------------------
8
- If you've used a rails generator, or required the file 'dragonfly/rails/images.rb', then this step will be already done for you.
9
-
10
- Suppose we have a dragonfly app
11
-
12
- app = Dragonfly::App[:my_app_name]
13
-
14
- We can define an accessor on ActiveRecord models using
15
-
16
- Dragonfly.active_record_macro(:image, app)
17
-
18
- The first argument is the prefix for the accessor macro (in this case 'image').
19
-
20
- Adding accessors
21
- ----------------
22
- Now we have the method `image_accessor` available in our model classes, which we can use as many times as we like
23
-
24
- class Album
25
- image_accessor :cover_image
26
- image_accessor :band_photo # Note: this is a different image altogether, not a thumbnail of cover_image
27
- end
28
-
29
- For each accessor, we need a database field ..._uid, as a string, so in our migrations:
30
-
31
- class MyMigration < ActiveRecord::Migration
32
-
33
- def self.up
34
- add_column :albums, :cover_image_uid, :string
35
- add_column :albums, :band_photo_uid, :string
36
- end
37
-
38
- def self.down
39
- remove_column :albums, :cover_image_uid
40
- remove_column :albums, :band_photo_uid
41
- end
42
-
43
- end
44
-
45
- Using the accessors
46
- -------------------
47
-
48
- We can use the attribute much like other other active record attributes:
49
-
50
- album = Album.new
51
-
52
- album.cover_image = "\377???JFIF\000\..." # can assign as a string...
53
- album.cover_image = File.new('path/to/my_image.png') # ... or as a file...
54
- album.cover_image = some_tempfile # ... or as a tempfile
55
-
56
- album.cover_image # => #<Dragonfly::ActiveRecordExtensions::Attachment:0x103ef6128...
57
-
58
- album.cover_image = nil
59
- album.cover_image # => nil
60
-
61
- We can inspect properties of the attribute
62
-
63
- album.cover_image.width # => 280
64
- album.cover_image.height # => 140
65
- album.cover_image.number_of_colours # => 34703 (can also use American spelling)
66
- album.cover_image.mime_type # => 'image/png'
67
-
68
- The properties available (i.e. 'width', etc.) come from the app's registered analysers - see {file:Analysers.md Analysers}.
69
-
70
- We can play around with the data
71
-
72
- album.cover_image.data # => "\377???JFIF\000\..."
73
- album.cover_image.to_file('out.png') # writes to file 'out.png' and returns a readable file object
74
- album.cover_image.tempfile # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a closed Tempfile object
75
- album.cover_image.file # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a readable (open) File object
76
- album.cover_image.file do |f| # Yields an open file object, returns the return value of
77
- data = f.read(256) # the block, and closes the file object
78
- end
79
- album.cover_image.path # => '/var/folders/st/strHv74sH044JPabSiODz...' i.e. the path of the tempfile
80
- album.cover_image.size # => 134507 (size in bytes)
81
-
82
- We can process the data
83
-
84
- temp_object = album.cover_image.process(:resize, :geometry => '20x20') # returns an ExtendedTempObject, with similar properties
85
- temp_object.width # => 20
86
- album.cover_image.width # => 280 (no change)
87
-
88
- album.cover_image.process!(:resize, :geometry => '20x20') # (operates on self)
89
- album.cover_image.width # => 20
90
-
91
- The available processing methods available (i.e. 'resize', etc.) come from the {Dragonfly} app's registered processors - see {file:Processing.md Processing}
92
-
93
- We can encode the data
94
-
95
- temp_object = album.cover_image.encode(:gif) # returns an ExtendedTempObject, with similar properties
96
- temp_object.mime_type # => 'image/gif'
97
- album.cover_image.mime_type # => 'image/png' (no change)
98
-
99
- album.cover_image.encode!(:gif) # (operates on self)
100
- album.cover_image.mime_type # => 'image/gif'
101
-
102
- The encoding is implemented by the {Dragonfly} app's registered encoders (which will usually just be one) - see {file:Encoding.md Encoding}
103
-
104
- If we have a combination of processing and encoding that we often use, e.g.
105
-
106
- album.cover_image.process(:resize_and_crop, :width => 300, :height => 200, :gravity => 'nw').encode(:gif)
107
-
108
- then we can register a shortcut (see {file:Shortcuts.md Shortcuts}) and use that with `transform`, e.g.
109
-
110
- album.cover_image.transform('300x200#nw', :gif) # returns an ExtendedTempObject, like process and encode above
111
- album.cover_image.transform!('300x200#nw', :gif) # (operates on self)
112
-
113
- Persisting
114
- ----------
115
- When the model is saved, a before_save callback persists the data to the {Dragonfly::App App}'s configured datastore (see {file:DataStorage.md DataStorage})
116
- The uid column is then filled in.
117
-
118
- album = Album.new
119
-
120
- album.cover_image_uid # => nil
121
-
122
- album.cover_image = File.new('path/to/my_image.png')
123
- album.cover_image_uid # => 'PENDING' (actually a Dragonfly::ActiveRecordExtensions::PendingUID)
124
-
125
- album.save
126
- album.cover_image_uid # => '2009/12/05/170406_file' (some unique uid, used by the datastore)
127
-
128
- URLs
129
- ----
130
- Once the model is saved, we can get a url for the image (which is served by the Dragonfly {Dragonfly::App App} itself):
131
-
132
- album.cover_image.url # => '/media/2009/12/05/170406_file' (Note there is no extension)
133
- album.cover_image.url(:png) # => '/media/2009/12/05/170406_file.png'
134
- album.cover_image.url('300x200#nw', :gif) # => '/media/2009/12/05/170406_file.tif?m=resize_and_crop&o[height]=...'
135
-
136
- Note that any arguments given to `url` are of the same form as those used for `transform`, i.e. those registered as shortcuts (see {file:Shortcuts.md Shortcuts})
137
- These urls are what you would use in, for example, html views.
138
-
139
- Validations
140
- -----------
141
- `validates_presence_of` and `validates_size_of` work out of the box, and Dragonfly provides two more,
142
- `validates_property` and `validates_mime_type_of` (which is actually just a thin wrapper around `validates_property`).
143
-
144
- class Album
145
-
146
- validates_presence_of :cover_image
147
- validates_size_of :cover_image, :maximum => 500.kilobytes
148
- validates_mime_type_of :cover_image, :in => %w(image/jpeg image/png image/gif)
149
- validates_property :width, :of => :cover_image, :in => (0..400)
150
-
151
- # ...
152
- end
153
-
154
- The property argument of `validates_property` will generally be one of the registered analyser properties as described in {file:Analysers.md Analysers}.
155
- However it would actually work for arbitrary properties, including those of non-dragonfly model attributes.
156
- See {Dragonfly::ActiveRecordExtensions::Validations Validations} for more info.
157
-
158
- Name and extension
159
- ------------------
160
- If the object assigned is a file, or responds to `original_filename` (as is the case with file uploads in Rails, etc.), then `name` and `ext` will be set.
161
-
162
- album.cover_image = File.new('path/to/my_image.png')
163
-
164
- album.cover_image.name # => 'my_image.png'
165
- album.cover_image.ext # => 'png'
166
-
167
-
168
- 'Magic' Attributes
169
- ------------------
170
- The only model column necessary for the migration, as described above, is the uid column, e.g. `cover_image_uid`.
171
- However, in many cases you may want to record some other properties in the database, whether it be for using in sql queries, or
172
- for caching an attribute for performance reasons.
173
-
174
- For the properties `name`, `ext`, `size` and any of the registered analysis methods (e.g. `width`, etc. in the examples above),
175
- this is done automatically for you, if the corresponding column exists.
176
- For example:
177
-
178
- In the migration:
179
-
180
- add_column :albums, :cover_image_ext, :string
181
- add_column :albums, :cover_image_width, :integer
182
-
183
- These are automatically set when assigned:
184
-
185
- album.cover_image = File.new('path/to/my_image.png')
186
-
187
- album.cover_image_ext # => 'png'
188
- album.cover_image_width # => 280
189
-
190
- They can be used to avoid retrieving data from the datastore for analysis (e.g. if you've used something like S3 to store data - see {file:DataStorage.md DataStorage})
191
-
192
- album = Album.first
193
-
194
- album.cover_image.ext # => 'png' - no need to retrieve data - takes it from `cover_image_ext`
195
- album.cover_image.width # => 280 - no need to retrieve data - takes it from `cover_image_width`
196
- album.cover_image.size # => 134507 - but it needs to retrieve data from the data store, then analyse
@@ -1,189 +0,0 @@
1
- Example Use Cases
2
- =================
3
-
4
- This document is concerned with different Dragonfly configurations, for various use cases.
5
-
6
- In a Rails app the configuration would generally be done in an initializer.
7
-
8
- In other Rack-based apps it could be config.ru, or anywhere where the application is generally set up.
9
-
10
- Image thumbnails in Rails
11
- -------------------------
12
- See {file:UsingWithRails}
13
-
14
-
15
- Image thumbnails in Rails, hosted on Heroku with S3 storage
16
- -----------------------------------------------------------
17
- {http://heroku.com Heroku} is a commonly used platform for hosting Rack-based websites.
18
- The following assumes your site is set up for deployment onto Heroku.
19
-
20
- The default configuration won't work out of the box for Heroku, because
21
-
22
- - Heroku doesn't allow saving files to the filesystem (although it does use tempfiles)
23
- - We won't need {http://tomayko.com/src/rack-cache/ Rack::Cache} on Heroku because it already uses the caching proxy {http://varnish.projects.linpro.no/ Varnish}, which we can make use of
24
-
25
- Instead of the normal {Dragonfly::DataStorage::FileDataStore FileDataStore}, we can use the {Dragonfly::DataStorage::S3DataStore S3DataStore}.
26
- Amazon's {http://aws.amazon.com/s3 S3} is a commonly used platform for storing data.
27
-
28
- The following assumes you have an S3 account set up, and know your provided 'access key' and 'secret'.
29
-
30
- ### Rails 2.3
31
-
32
- environment.rb:
33
-
34
- config.gem 'rmagick', :lib => 'RMagick'
35
- gem 'aws-s3', :lib => 'aws/s3'
36
- config.gem 'dragonfly'
37
-
38
- and
39
- .gems:
40
-
41
- dragonfly
42
- aws-s3
43
-
44
- ### Rails 3
45
-
46
- Gemfile:
47
-
48
- gem 'rmagick', '2.12.2', :require => 'RMagick'
49
- gem 'aws-s3', :require => 'aws/s3'
50
- gem 'dragonfly'
51
-
52
- Apparently to use Bundler you need to switch to the 'Bamboo' stack - see {http://docs.heroku.com/bamboo}
53
-
54
- ### All versions
55
-
56
- Initializer (e.g. config/initializers/dragonfly.rb):
57
-
58
- require 'dragonfly'
59
- app = Dragonfly::App[:images]
60
- app.configure_with(Dragonfly::Config::HerokuRailsImages, 'my_bucket_name')
61
- Dragonfly.active_record_macro(:image, app)
62
-
63
- The datastore remains as the {Dragonfly::DataStorage::FileDataStore FileDataStore} for non-production environments.
64
-
65
- environment.rb (application.rb in Rails 3):
66
-
67
- config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :images
68
-
69
- We don't store the S3 access key and secret in the repository, rather we use Heroku's
70
- {http://docs.heroku.com/config-vars config variables} using the command line (we only have to do this once).
71
-
72
- From your app's directory:
73
-
74
- heroku config:add S3_KEY=XXXXXXXXX S3_SECRET=XXXXXXXXXX
75
-
76
- Obviously you replace 'XXXXXXXXX' with your access key and secret.
77
-
78
- Now you can benefit use Dragonfly in the normal way, benefitting from super-fast images served straight from Heroku's cache!
79
-
80
- NOTE: HEROKU'S CACHE IS CLEARED EVERY TIME YOU DEPLOY.
81
- If this is an issue you may want to look into using something like a Memcached add-on, or maybe an after-deploy hook for hitting specific Dragonfly urls you want to cache, etc.
82
- It won't be a problem for most sites though.
83
-
84
-
85
- Attaching files to ActiveRecord models with no processing or encoding
86
- ---------------------------------------------------------------------
87
- Although Dragonfly is normally concerned with processing and encoding, you may want to just use it with arbitrary uploaded files
88
- (e.g. .doc, .xls, .pdf files, etc.) without processing or encoding them, so as to still benefit from the {file:ActiveRecord ActiveRecord Extensions} API.
89
-
90
- The below shows how to do it in Rails, but the principles are the same in any context.
91
-
92
- Initializer, e.g. config/initializers/dragonfly.rb:
93
-
94
- require 'dragonfly'
95
-
96
- app = Dragonfly::App[:attachments]
97
- app.configure_with(Dragonfly::Config::RailsDefaults) do |c|
98
- c.register_analyser(Dragonfly::Analysis::FileCommandAnalyser)
99
- c.register_encoder(Dragonfly::Encoding::TransparentEncoder)
100
- end
101
- Dragonfly.active_record_macro(:attachment, app)
102
-
103
- The {Dragonfly::Analysis::FileCommandAnalyser FileCommandAnalyser} is needed to know the mime-type of the content,
104
- and the {Dragonfly::Encoding::TransparentEncoder TransparentEncoder} is like a 'dummy' encoder which does nothing
105
- (the way to switch off encoding will be simplified in future versions of Dragonfly).
106
-
107
- environment.rb (application.rb in Rails 3):
108
-
109
- config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :attachments
110
-
111
- If a user uploads a file called 'report.pdf', then normally the original file extension will be lost.
112
- Thankfully, to record it is as easy as adding an 'ext' column as well as the usual uid column to our migration
113
- (see {file:ActiveRecord} for more info about 'magic attributes'):
114
-
115
- add_column :my_models, :attachment_uid, :string
116
- add_column :my_models, :attachment_ext, :string
117
-
118
- Then we include a helper method in our model for setting the correct file extension when we link to the attachment:
119
-
120
- class MyModel < ActiveRecord::Base
121
-
122
- attachment_accessor :attachment
123
-
124
- def url_for_attachment
125
- attachment.url :format => attachment_ext
126
- end
127
- end
128
-
129
- Now we can add links to the attached file in our views:
130
-
131
- <%= link_to 'Attachment', @my_model.url_for_attachment %>
132
-
133
-
134
- Generating test data
135
- --------------------
136
- We may want to generate a load of test data in a test / populate script.
137
-
138
- Each {Dragonfly::App Dragonfly App} has a 'generate' method, which returns an {Dragonfly::ExtendedTempObject ExtendedTempObject} with generated data.
139
- The actual generation is delegated to the registered processors (along with any args passed in).
140
-
141
- For example, if our app is registered with the {Dragonfly::Processing::RMagickProcessor RMagickProcessor} (which is already done if using with one of
142
- the RMagick/RailsImage configurations)
143
-
144
- Dragonfly::App[:my_app].register_processor(Dragonfly::Processing::RMagickProcessor)
145
-
146
- then we can generate images of different sizes/formats):
147
-
148
- image = Dragonfly::App[:my_app].generate(300, 200) # creates a png image of size 300x200 (as an ExtendedTempObject)
149
- image.to_file('out.png') # writes to file 'out.png'
150
- image = Dragonfly::App[:my_app].generate(50, 50, :gif) # creates a gif image of size 50x50
151
-
152
-
153
- Text image replacement
154
- ----------------------
155
- A common technique for making sure a specific font is displayed on a website is replacing text with images.
156
-
157
- We can easily use Dragonfly to do this on-the-fly.
158
-
159
- Configuration (e.g. initializer in Rails):
160
-
161
- require 'dragonfly'
162
- Dragonfly::App[:text].configure_with(Dragonfly::Config::RMagickText) do |c|
163
- c.url_handler.path_prefix = '/text'
164
- end
165
-
166
- If using Rails, then in environment.rb (application.rb in Rails 3):
167
-
168
- config.middleware.insert_after 'Rack::Lock', 'Dragonfly::Middleware', :text
169
-
170
- You probably will want to insert Rack::Cache too or use some other caching proxy - see {file:UsingWithRails}.
171
-
172
- Then when we visit a url like
173
-
174
- url = Dragonfly::App[:text].url_for('some text', :text, :font_size => 30, :font_family => 'Monaco')
175
-
176
- we get a png image of the text. We could easily wrap this in some kind of helper if we use it often.
177
-
178
- This configuration uses the {Dragonfly::Processing::RMagickTextProcessor RMagickTextProcessor} processor.
179
- Options can be specified either css-like (e.g. `'font-family' => 'Helvetica'`), or with underscore-style symbols
180
- (e.g. `:font_family => 'Helvetica'`).
181
-
182
- Available options are `font` (see {http://www.imagemagick.org/RMagick/doc/draw.html#font}),
183
- `'font-family'`,
184
- `'stroke_color'`,
185
- `'color'`,
186
- `'font_style'`,
187
- `'font_stretch'`,
188
- `'font_weight'` and
189
- `'padding'` (or `'padding-left'`, `'padding-top'`, etc.)
@@ -1,114 +0,0 @@
1
- Getting Started
2
- ===============
3
-
4
- Below is a general guide for setting up and using Dragonfly.
5
-
6
- For setting up with Ruby on Rails, see {file:UsingWithRails UsingWithRails}.
7
-
8
- For more info about using Rack applications, see the docs at {http://rack.rubyforge.org/}
9
-
10
- Running as a Standalone Rack Application
11
- ----------------------------------------
12
-
13
- Basic usage of a dragonfly app involves storing data (e.g. images),
14
- then serving that data, either in its original form, processed, encoded or both.
15
-
16
- A basic rackup file `config.ru`:
17
-
18
- require 'rubygems'
19
- require 'dragonfly'
20
-
21
- Dragonfly::App[:my_app_name].configure do |c|
22
- # ...
23
- c.some_attribute = 'blah'
24
- # ...
25
- end
26
-
27
- run Dragonfly:App[:my_app_name]
28
-
29
- As you can see, this involves instantiating an app, configuring it (how data is stored,
30
- processing, encoding, etc.), then running it.
31
-
32
- You can have multiple dragonfly apps, each with their own configuration.
33
- Each app has a name, and is referred to by that name.
34
-
35
- Dragonfly::App[:images] # ===> Creates an app called 'images'
36
- Dragonfly::App[:images] # ===> Refers to the already created app 'images'
37
-
38
- Example: Using to serve resized images
39
- --------------------------------------
40
-
41
- `config.ru`:
42
-
43
- require 'rubygems'
44
- require 'dragonfly'
45
- require 'rack/cache'
46
-
47
- app = Dragonfly::App[:images]
48
- app.configure_with(Dragonfly::Config::RMagickImages)
49
-
50
- use Rack::Cache,
51
- :verbose => true,
52
- :metastore => 'file:/var/cache/rack/meta',
53
- :entitystore => 'file:/var/cache/rack/body'
54
-
55
- run app
56
-
57
- This configures the app to use the RMagick {Dragonfly::Processing::RMagickProcessor processor},
58
- {Dragonfly::Encoding::RMagickEncoder encoder} and {Dragonfly::Analysis::RMagickAnalyser analyser}.
59
- By default the {Dragonfly::DataStorage::FileDataStore file data store} is used.
60
-
61
- Elsewhere in our code:
62
-
63
- app = Dragonfly::App[:images]
64
-
65
- # Store
66
- uid = app.store(File.new('path/to/image.png')) # ===> returns a unique uid for that image, "2009/11/29/145804_file"
67
-
68
- # Get the url for a thumbnail
69
- url = app.url_for(uid, '30x30', :gif) # ===> "/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x30"
70
-
71
- Now when we visit the url `/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x30` in the browser, we get the resized
72
- image!
73
-
74
- Caching
75
- -------
76
- Processing and encoding can be an expensive operation. The first time we visit the url,
77
- the image is processed, and there might be a short delay and getting the response.
78
-
79
- However, dragonfly apps send `Cache-Control` and `ETag` headers in the response, so we can easily put a caching
80
- proxy like {http://varnish.projects.linpro.no Varnish}, {http://www.squid-cache.org Squid},
81
- {http://tomayko.com/src/rack-cache/ Rack::Cache}, etc. in front of the app.
82
-
83
- In the example above, we've put the middleware {http://tomayko.com/src/rack-cache/ Rack::Cache} in front of the app.
84
- So although the first time we access the url the content is processed, every time after that it is received from the
85
- cache, and is served super quick!
86
-
87
- Avoiding Denial-of-service attacks
88
- ----------------------------------
89
- The url given above, `/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x30`, could easily be modified to
90
- generate all different sizes of thumbnails, just by changing the size, e.g.
91
-
92
- `/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x31`,
93
-
94
- `/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x32`,
95
-
96
- etc.
97
-
98
- Therefore the app can protect the url by generating a unique sha from a secret specified by you
99
-
100
- Dragonfly::App[:images].url_handler.configure do |c|
101
- c.protect_from_dos_attacks = true # Actually this is true by default
102
- c.secret = 'You should supply some random secret here'
103
- end
104
-
105
- Then the required urls become something more like
106
-
107
- `/2009/12/10/215214_file.gif?m=resize&o[geometry]=30x30&s=aa78e877ad3f6bc9`,
108
-
109
- with a sha parameter on the end.
110
- If we try to hack this url to get a different thumbnail,
111
-
112
- `/2009/12/10/215214_file.gif?m=resize&o[geometry]=30x31&s=aa78e877ad3f6bc9`,
113
-
114
- then we get a 400 (bad parameters) error.