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,33 +0,0 @@
1
- Dragonfly is a {http://rack.rubyforge.org Rack} framework for on-the-fly image handling in Ruby.
2
-
3
- It is suitable for using with web frameworks such as Rails(2.3 and 3), Sinatra, etc.
4
-
5
- I actually lied about image handling - it can be used for any type of content.
6
-
7
- See the links on the right for more info.
8
-
9
- Installation
10
- ------------
11
-
12
- gem install dragonfly
13
-
14
- Add-ons
15
- -------
16
- For third-party add-ons, see [the Add-ons wiki](http://github.com/markevans/dragonfly/wiki/Dragonfly-add-ons)
17
-
18
- Issues
19
- ------
20
- Please use the <a href="http://github.com/markevans/dragonfly/issues">github issue tracker</a>.
21
-
22
- Suggestions/Questions
23
- ---------------------
24
- {http://groups.google.com/group/dragonfly-users}
25
-
26
- Credits
27
- -------
28
- - [Mark Evans](http://github.com/markevans) (author)
29
- - Loads of helpful comments, issues, questions, suggestions and insults from others - you know who you are!
30
-
31
- Copyright
32
- ---------
33
- Copyright (c) 2009-2010 Mark Evans. See LICENSE for details.
@@ -1,40 +0,0 @@
1
- Mime Types
2
- ==========
3
-
4
- Responses from the Dragonfly app have the HTTP 'Content-Type' header set.
5
-
6
- This is decided by the first found from:
7
-
8
- 1. The requested format (e.g. when encode is specifically called)
9
- 2. The original file extension (you can configure it to ignore this if you wish)
10
- 3. Analyse the content using the analyser's 'format' method (if exists)
11
- 4. Analyse the content using the analyser's 'mime_type' method (if exists)
12
- 5. Use the fallback mime-type (default 'application/octet-stream')
13
-
14
- Note that 'format' means 'jpg', 'png', etc. whereas mime-type would be 'image/jpeg', image/png', etc.
15
- Formats are mapped to mime-types using the app's registered list of mime-types.
16
-
17
- Registered mime-types
18
- ---------------------
19
- Registered mime-types default to the list given by Rack (see {http://rack.rubyforge.org/doc/Rack/Mime.html#MIME_TYPES Rack mime-types}).
20
-
21
- To register a mime-type for the format 'egg':
22
-
23
- Dragonfly[:my_app].register_mime_type(:egg, 'fried/egg')
24
-
25
- You can also do this inside a configuration block.
26
-
27
- Analysers
28
- ---------
29
- The {Dragonfly::Analysis::FileCommandAnalyser FileCommandAnalyser} has a `mime_type` method and the
30
- {Dragonfly::ImageMagick::Analyser ImageMagick Analyser} has a `format` method.
31
-
32
- These are both registered by default when you use the preconfigured 'dragonfly/rails/images' file.
33
-
34
- Fallback mime-type
35
- ------------------
36
- By default this is 'application/octet-stream', but it can be changed using
37
-
38
- Dragonfly[:my_app].fallback_mime_type = 'meaty/beef'
39
-
40
- This can also be done inside a configuration block.
@@ -1,441 +0,0 @@
1
- Using with Models
2
- =================
3
-
4
- You can extend ActiveModel-compatible models to make working with content such as images
5
- as easy as working with strings or numbers!
6
-
7
- The examples below assume an initialized Dragonfly app, e.g.
8
-
9
- app = Dragonfly[:images]
10
-
11
- ActiveRecord
12
- ------------
13
- If you've required 'dragonfly/rails/images', then the following step will be already done for you.
14
- Otherwise:
15
-
16
- app.define_macro(ActiveRecord::Base, :image_accessor)
17
-
18
- defines the macro `image_accessor` on any ActiveRecord models.
19
-
20
- Mongoid
21
- -------
22
-
23
- app.define_macro_on_include(Mongoid::Document, :image_accessor)
24
-
25
- defines the macro `image_accessor` on any models that include `Mongoid::Document`
26
-
27
- CouchRest::Model
28
- -------
29
- app.define_macro(CouchRest::Model::Base, :image_accessor)
30
-
31
- defines the macro `image_accessor` on any models inherited from `CouchRest::Model::Base`.
32
-
33
- Adding accessors
34
- ----------------
35
- Now we have the method `image_accessor` available in our model classes, which we can use as many times as we like
36
-
37
- class Album
38
- image_accessor :cover_image
39
- image_accessor :band_photo # Note: this is a different image altogether, not a thumbnail of cover_image
40
- end
41
-
42
- Each accessor (e.g. `cover_image`) depends on a string field to actually hold the datastore uid,
43
- named by appending the suffix `_uid` (e.g. `cover_image_uid`).
44
-
45
- For example, ActiveRecord models need a migration such as:
46
-
47
- class MyMigration < ActiveRecord::Migration
48
-
49
- def self.up
50
- add_column :albums, :cover_image_uid, :string
51
- add_column :albums, :band_photo_uid, :string
52
- end
53
-
54
- def self.down
55
- remove_column :albums, :cover_image_uid
56
- remove_column :albums, :band_photo_uid
57
- end
58
-
59
- end
60
-
61
- Using the accessors
62
- -------------------
63
-
64
- We can use the attribute much like other other model attributes:
65
-
66
- @album = Album.new
67
-
68
- @album.cover_image = "\377???JFIF\000\..." # can assign as a string...
69
- @album.cover_image = File.new('path/to/my_image.png') # ... or as a file...
70
- @album.cover_image = some_tempfile # ... or as a tempfile...
71
- @album.cover_image = Pathname.new('some/path.gif') # ... or as a pathname...
72
- @album.cover_image = @album.band_photo # ... or as another Dragonfly attachment
73
-
74
- @album.cover_image # => #<Dragonfly::ActiveModelExtensions::Attachment:0x103ef6128...
75
-
76
- @album.cover_image = nil
77
- @album.cover_image # => nil
78
-
79
- We can inspect properties of the attribute
80
-
81
- @album.cover_image.width # => 280
82
- @album.cover_image.height # => 140
83
- @album.cover_image.number_of_colours # => 34703
84
- @album.cover_image.mime_type # => 'image/png'
85
-
86
- The properties available (i.e. 'width', etc.) come from the app's registered analysers - see {file:Analysers.md Analysers}.
87
-
88
- We can play around with the data
89
-
90
- @album.cover_image.data # => "\377???JFIF\000\..."
91
- @album.cover_image.to_file('out.png') # writes to file 'out.png' and returns a readable file object
92
- @album.cover_image.to_file('out.png',
93
- :mode => 0600,
94
- :mkdirs => false
95
- )
96
- @album.cover_image.tempfile # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a closed Tempfile object
97
- @album.cover_image.file # => #<File:/var/folders/st/strHv74sH044JPabSiODz... a readable (open) File object
98
- @album.cover_image.file do |f| # Yields an open file object, returns the return value of
99
- data = f.read(256) # the block, and closes the file object
100
- end
101
- @album.cover_image.path # => '/var/folders/st/strHv74sH044JPabSiODz...' i.e. the path of the tempfile
102
- @album.cover_image.size # => 134507 (size in bytes)
103
-
104
- We can process the data
105
-
106
- image = @album.cover_image.process(:thumb, '20x20') # returns a 'Job' object, with similar properties
107
- image.width # => 20
108
- @album.cover_image.width # => 280 (no change)
109
-
110
- The available processing methods available (i.e. 'thumb', etc.) come from the {Dragonfly} app's registered processors - see {file:Processing.md Processing}
111
-
112
- We can encode the data
113
-
114
- image = @album.cover_image.encode(:gif) # returns a 'Job' object, with similar properties
115
- image.format # => :gif
116
- @album.cover_image.format # => :png (no change)
117
-
118
- The encoding is implemented by the {Dragonfly} app's registered encoders (which will usually just be one) - see {file:Encoding.md Encoding}
119
-
120
- We can use configured shortcuts for processing/encoding, and chain them:
121
-
122
- @album.cover_image.thumb('300x200#ne') # => returns a 'Job' object, with similar properties
123
-
124
- We can chain all these things much like ActiveRecord scopes:
125
-
126
- @album.cover_image.png.thumb('300x200#ne').process(:greyscale).encode(:tiff)
127
-
128
- Because the processing/encoding methods are lazy, no actual processing or encoding is done until a method like `data`, `file`, `to_file`, `width`, etc. is called.
129
- You can force the processing to be done if you must by then calling `apply`.
130
-
131
- @album.cover_image.process(:greyscale).apply
132
-
133
- Assigning from a url
134
- --------------------
135
- Dragonfly provides an accessor for assigning directly from a url:
136
-
137
- @album.cover_image_url = 'http://some.url/file.jpg'
138
-
139
- You can put this in a form view, e.g. in rails erb:
140
-
141
- <% form_for @album, :html => {:multipart => true} do |f| %>
142
- ...
143
- <%= f.text_field :cover_image_url %>
144
- ...
145
- <% end %>
146
-
147
- Removing an attachment via a form
148
- ---------------------------------
149
- Normally unassignment of an attachment is done like any other attribute, by setting to nil
150
-
151
- @album.cover_image = nil
152
-
153
- but this can't be done via a form - instead `remove_<attachment_name>` is provided, which can be used with a checkbox:
154
-
155
- <%= f.check_box :remove_cover_image %>
156
-
157
- Retaining across form redisplays
158
- --------------------------------
159
- When a model fails validation, you don't normally want to have to upload your attachment again, so you can avoid having to do this by
160
- including a hidden field in your form `retained_<attribute_name>`, e.g.
161
-
162
- <% form_for @album, :html => {:multipart => true} do |f| %>
163
- ...
164
- <%= f.file_field :cover_image %>
165
- <%= f.hidden_field :retained_cover_image %>
166
- ...
167
- <% end %>
168
-
169
- Persisting
170
- ----------
171
- 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})
172
- The uid column is then filled in.
173
-
174
- @album = Album.new
175
-
176
- @album.cover_image_uid # => nil
177
-
178
- @album.cover_image = File.new('path/to/my_image.png')
179
- @album.cover_image_uid # => nil
180
-
181
- @album.save
182
- @album.cover_image_uid # => '2009/12/05/file.png' (some unique uid, used by the datastore)
183
-
184
- URLs
185
- ----
186
- Once the model is saved, we can get a url for the image (which is served by the Dragonfly {Dragonfly::App App} itself), and for its processed/encoded versions:
187
-
188
- @album.cover_image.url # => '/media/BAhbBlsHOgZmIhgy...'
189
- @album.cover_image.thumb('300x200#nw').url # => '/media/BAhbB1sYusgZhgyM...'
190
- @album.cover_image.process(:greyscale).jpg.url # => '/media/BnA6CnRodW1iIg8z...'
191
-
192
- Because the processing/encoding methods (including shortcuts like `thumb` and `jpg`) are lazy, no processing or encoding is actually done.
193
-
194
- Validations
195
- -----------
196
- `validates_presence_of` and `validates_size_of` work out of the box, and Dragonfly also provides `validates_property`.
197
-
198
- class Album
199
-
200
- validates_presence_of :cover_image
201
- validates_size_of :cover_image, :maximum => 500.kilobytes
202
-
203
- validates_property :format, :of => :cover_image, :in => [:jpeg, :png, :gif]
204
- # ..or..
205
- validates_property :mime_type, :of => :cover_image, :as => 'image/jpeg', :case_sensitive => false
206
-
207
- validates_property :width, :of => :cover_image, :in => (0..400), :message => "é demais cara!"
208
-
209
- # ...
210
- end
211
-
212
- The property argument of `validates_property` will generally be one of the registered analyser properties as described in {file:Analysers.md Analysers}.
213
- However it would actually work for arbitrary properties, including those of non-dragonfly model attributes.
214
-
215
- `validates_property` can also take a proc for the message, yielding the actual value and the model
216
-
217
- validates_property :width, :of => :cover_image, :in => (0..400),
218
- :message => proc{|actual, model| "Unlucky #{model.title} - was #{actual}" }
219
-
220
- Name and extension
221
- ------------------
222
- If the object assigned is a file, or responds to `original_filename` (as is the case with file uploads in Rails, etc.), then `name` will be set.
223
-
224
- @album.cover_image = File.new('path/to/my_image.png')
225
-
226
- @album.cover_image.name # => 'my_image.png'
227
- @album.cover_image.ext # => 'png'
228
-
229
- Meta data
230
- ---------
231
- You can store metadata along with the content data of your attachment:
232
-
233
- @album.cover_image = File.new('path/to/my_image.png')
234
- @album.cover_image.meta = {:taken => Date.yesterday}
235
- @album.save!
236
-
237
- @album.cover_image.meta # => {:model_class=>"Album",
238
- # :model_attachment=>:cover_image,
239
- # :taken=>Sat, 11 Sep 2010}
240
-
241
- As you can see, a couple of things are added by the model. You can also access this directly on the {Dragonfly::Job Job} object.
242
-
243
- app.fetch(@album.cover_image_uid).meta # => {:model_class=>"Album", ...}
244
-
245
- Meta data can be useful because at the time that Dragonfly serves content, it doesn't have access to your model, but it does
246
- have access to the meta data that was stored alongside the content, so you could use it to provide custom response headers, etc.
247
- (see {file:Configuration}).
248
-
249
- Callbacks
250
- ---------
251
- **after_assign**
252
-
253
- `after_assign` can be used to do something every time content is assigned:
254
-
255
- class Person
256
- image_accessor :mugshot do
257
- after_assign{|a| a.process!(:rotate, 90) } # 'a' is the attachment itself
258
- end
259
- end
260
-
261
- person.mugshot = Pathname.new('some/path.png') # after_assign callback is called
262
- person.mugshot = nil # after_assign callback is NOT called
263
-
264
- Inside the block, you can call methods on the model instance directly (`self` is the model):
265
-
266
- class Person
267
- image_accessor :mugshot do
268
- after_assign{|a| a.process!(:rotate, angle) }
269
- end
270
-
271
- def angle
272
- 90
273
- end
274
- end
275
-
276
- Alternatively you can pass in a symbol, corresponding to a model instance method:
277
-
278
- class Person
279
- image_accessor :mugshot do
280
- after_assign :rotate_it
281
- end
282
-
283
- def rotate_it
284
- mugshot.process!(:rotate, 90)
285
- end
286
- end
287
-
288
- You can register more than one `after_assign` callback.
289
-
290
- **after_unassign**
291
-
292
- `after_unassign` is similar to `after_assign`, but is only called when the attachment is unassigned
293
-
294
- person.mugshot = Pathname.new('some/path.png') # after_unassign callback is NOT called
295
- person.mugshot = nil # after_unassign callback is called
296
-
297
- Up-front thumbnailing
298
- ---------------------
299
- The best way to create different versions of content such as thumbnails is generally on-the-fly, however if you _must_
300
- create another version _on-upload_, then you could create another accessor and automatically copy to it using `copy_to`.
301
-
302
- class Person
303
- image_accessor :mugshot do
304
- copy_to(:smaller_mugshot){|a| a.thumb('200x200#') }
305
- end
306
- image_accessor :smaller_mugshot
307
- end
308
-
309
- person.mugshot = Pathname.new('some/400x300/image.png')
310
-
311
- person.mugshot # ---> 400x300 image
312
- person.smaller_mugshot # ---> 200x200 image
313
-
314
- In the above example you would need both a `mugshot_uid` field and a `smaller_mugshot_uid` field on your model.
315
-
316
- Storage options
317
- ---------------
318
- Some datastores take options when calling `store` - you can pass these through using `storage_xxx` methods, e.g.
319
-
320
- **storage_path**
321
-
322
- The {Dragonfly::DataStorage::FileDataStore FileDataStore} and {Dragonfly::DataStorage::S3DataStore S3DataStore} both
323
- can take a `:path` option to specify where to store the content (which will also become the uid for that content)
324
-
325
- class Person
326
- image_accessor :mugshot do
327
- storage_path{ "some/path/#{first_name}/#{rand(100)}" } # You can call model instance methods (like 'first_name') directly
328
- end
329
- end
330
-
331
- or
332
-
333
- class Person
334
- image_accessor :mugshot do
335
- storage_path :path_for_mugshot
336
- end
337
-
338
- def path_for_mugshot
339
- "some/path/#{first_name}/#{rand(100)}"
340
- end
341
- end
342
-
343
- or you can also yield the attachment itself
344
-
345
- storage_path{|a| "some/path/#{a.width}x#{a.height}.#{a.format}" }
346
-
347
- **BEWARE!!!!** you must make sure the path (which will become the uid for the content) is unique and changes each time the content
348
- is changed, otherwise you could have caching problems, as the generated urls will be the same for the same uid.
349
-
350
- **BEWARE No. 2!!!!** using `id` in the `storage_path` won't generally work on create, because Dragonfly stores the content in a call to `before_save`,
351
- at which point the `id` won't yet exist.
352
-
353
- You can pass any options through to the datastore using `storage_xxx` methods, or all at once using `storage_opts`:
354
-
355
- class Person
356
- image_accessor :mugshot do
357
- storage_opts do |a|
358
- {
359
- :path => "some/path/#{id}/#{rand(100)}",
360
- :other => 'option'
361
- }
362
- end
363
- end
364
- end
365
-
366
- "Magic" Attributes
367
- ------------------
368
- An accessor like `cover_image` only relies on the accessor `cover_image_uid` to work.
369
- However, in some cases you may want to record some other properties, whether it be for using in queries, or
370
- for caching an attribute for performance reasons, etc.
371
-
372
- For the properties `name`, `ext`, `size` and any of the registered analysis methods (e.g. `width`, etc. in the examples above),
373
- this is done automatically for you, if the corresponding accessor exists.
374
-
375
- For example - with ActiveRecord, given the migration:
376
-
377
- add_column :albums, :cover_image_width, :integer
378
-
379
- This will automatically be set when assigned:
380
-
381
- @album.cover_image = File.new('path/to/my_image.png')
382
-
383
- @album.cover_image_width # => 280
384
-
385
- They can be used to avoid retrieving data from the datastore for analysis
386
-
387
- @album = Album.first
388
-
389
- @album.cover_image.width # => 280 - no need to retrieve data - takes it from `cover_image_width`
390
- @album.cover_image.size # => 134507 - but this needs to retrieve data from the data store, then analyse
391
-
392
- Furthermore, any magic attributes you add a field for will be added to the meta data for that attachment (and so can be used when Dragonfly serves the content
393
- for e.g. setting custom response headers based on that meta - see {file:Configuration}).
394
-
395
- Custom Model
396
- ------------
397
- The accessors only require that your model class implements `before_save`, `before_destroy` and `validates_each`
398
- (if using validations), as well as of course the `..._uid` field for storing the datastore uid.
399
-
400
- Here is an example of a minimal ActiveModel `Album` model:
401
-
402
- class CustomModel::Base
403
-
404
- extend ActiveModel::Callbacks
405
- define_model_callbacks :save, :destroy
406
-
407
- include ActiveModel::Validations # if needed
408
-
409
- def save
410
- _run_save_callbacks {
411
- # do some saving!
412
- }
413
- end
414
-
415
- def destroy
416
- _run_destroy_callbacks {
417
- # do some destroying!
418
- }
419
- end
420
-
421
- end
422
-
423
- Define our `image_accessor` macro...
424
-
425
- app.define_macro(CustomModel::Base, :image_accessor)
426
-
427
- ...which is used by `Album`:
428
-
429
- class Album < CustomModel::Base
430
-
431
- def cover_image_uid=
432
- # ...
433
- end
434
-
435
- def cover_image_uid
436
- # ...
437
- end
438
-
439
- image_accessor :cover_image
440
-
441
- end