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
@@ -0,0 +1,353 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dragonfly::Content do
4
+
5
+ let(:app) { test_app }
6
+
7
+ let(:content) { Dragonfly::Content.new(app) }
8
+
9
+ describe "initializing" do
10
+ it "allows initializing with content and meta" do
11
+ content = Dragonfly::Content.new(app, "things", 'some' => 'meta')
12
+ content.data.should == 'things'
13
+ content.meta.should == {'some' => 'meta'}
14
+ end
15
+ end
16
+
17
+ describe "temp_object" do
18
+ it "has one from the beginning" do
19
+ content.temp_object.should be_a(Dragonfly::TempObject)
20
+ end
21
+ end
22
+
23
+ describe "meta" do
24
+ it "defaults to an empty hash" do
25
+ content.meta.should == {}
26
+ end
27
+
28
+ it "sets meta" do
29
+ content.meta = {"hello" => 'there'}
30
+ content.meta.should == {"hello" => 'there'}
31
+ end
32
+
33
+ it "adds meta and returns itself" do
34
+ content.meta = {'hello' => 'there'}
35
+ content.add_meta('wassup' => 'guys?').should == content
36
+ content.meta.should == {'hello' => 'there', 'wassup' => 'guys?'}
37
+ end
38
+ end
39
+
40
+ describe "name" do
41
+ it "defaults to nil" do
42
+ content.name.should be_nil
43
+ end
44
+
45
+ it "gets taken from the meta" do
46
+ content.meta["name"] = 'some.name'
47
+ content.name.should == 'some.name'
48
+ end
49
+
50
+ it "has basename/name/ext setters" do
51
+ content.name = 'hello.there'
52
+ content.name.should == 'hello.there'
53
+ content.basename.should == 'hello'
54
+ content.ext.should == 'there'
55
+ content.ext = 'schmo'
56
+ content.name.should == 'hello.schmo'
57
+ end
58
+ end
59
+
60
+ describe "mime_type" do
61
+ it "takes it from the extension" do
62
+ content.name = "thing"
63
+ content.mime_type.should == "application/octet-stream"
64
+ content.name = "thing.png"
65
+ content.mime_type.should == "image/png"
66
+ end
67
+ end
68
+
69
+ describe "process!" do
70
+ it "calls the app's processor on itself and returns itself" do
71
+ app.add_processor(:shizzle){}
72
+ app.get_processor(:shizzle).should_receive(:call).with(content, 'args')
73
+ content.process!(:shizzle, 'args').should == content
74
+ end
75
+ end
76
+
77
+ describe "generate!" do
78
+ it "calls the app's generator on itself and returns itself" do
79
+ app.add_generator(:shizzle){}
80
+ app.get_generator(:shizzle).should_receive(:call).with(content, 'args')
81
+ content.generate!(:shizzle, 'args').should == content
82
+ end
83
+ end
84
+
85
+ describe "analyse" do
86
+ before do
87
+ app.add_analyser(:len){|content| content.size }
88
+ content.update("shizzle")
89
+ end
90
+
91
+ it "calls the app's analyser on itself" do
92
+ app.get_analyser(:len).should_receive(:call).with(content).and_return(7)
93
+ content.analyse(:len).should == 7
94
+ end
95
+
96
+ it "caches the result" do
97
+ content.analyse(:len).should == 7
98
+ app.get_analyser(:len).should_not_receive(:call)
99
+ content.analyse(:len).should == 7
100
+ end
101
+
102
+ it "caches it in the meta" do
103
+ content.meta["analyser_cache"].should be_nil
104
+ content.analyse(:len).should == 7
105
+ content.meta["analyser_cache"].should == {"len" => 7}
106
+ end
107
+
108
+ it "empties the cache if updated" do
109
+ content.analyse(:len).should == 7
110
+ content.meta["analyser_cache"].should == {"len" => 7}
111
+ content.update("something else")
112
+ content.meta["analyser_cache"].should be_nil
113
+ content.analyse(:len).should == 14
114
+ content.meta["analyser_cache"].should == {"len" => 14}
115
+ end
116
+ end
117
+
118
+ describe "update" do
119
+ it "updates the content" do
120
+ content.update("stuff")
121
+ content.data.should == 'stuff'
122
+ end
123
+
124
+ it "optionally updates the meta" do
125
+ content.update("stuff", 'meta' => 'here')
126
+ content.meta.should == {'meta' => 'here'}
127
+ end
128
+
129
+ it "returns itself" do
130
+ content.update('abc').should == content
131
+ end
132
+
133
+ it "can be updated with another content" do
134
+ content2 = Dragonfly::Content.new(app, "a", "b" => "c")
135
+ content.update(content2)
136
+ content.data.should == 'a'
137
+ content.meta['b'].should == 'c'
138
+ end
139
+
140
+ describe "meta name" do
141
+ let (:object) { "HI EVERYONE" }
142
+ let (:object_with_original_filename) {
143
+ obj = "Hi Guys"
144
+ def obj.original_filename; 'something.original'; end
145
+ obj
146
+ }
147
+
148
+ it "is nil if there is no original_filename" do
149
+ content.update(object)
150
+ content.meta['name'].should be_nil
151
+ end
152
+
153
+ it "sets the name to the original filename" do
154
+ content.update(object_with_original_filename)
155
+ content.meta['name'].should == 'something.original'
156
+ end
157
+
158
+ it "overrides original filename with the specified name" do
159
+ content.update(object_with_original_filename, 'name' => 'summink.else')
160
+ content.meta['name'].should == 'summink.else'
161
+ end
162
+
163
+ it "doesn't override a name already there" do
164
+ content.meta['name'] = 'already.here'
165
+ content.update(object_with_original_filename)
166
+ content.meta['name'].should == 'already.here'
167
+ end
168
+ end
169
+ end
170
+
171
+ describe "delegated methods to temp_object" do
172
+ it "data" do
173
+ content.data.should == ""
174
+ content.update("ASDF")
175
+ content.data.should == 'ASDF'
176
+ end
177
+
178
+ it "file" do
179
+ content.file.should be_a(File)
180
+ content.file.read.should == ""
181
+ content.update("sdf")
182
+ content.file.should be_a(File)
183
+ content.file.read.should == 'sdf'
184
+ content.file{|f| f.read.should == 'sdf'}
185
+ end
186
+
187
+ it "path" do
188
+ content.path.should =~ %r{\w+/\w+}
189
+ content.update(Pathname.new('/usr/eggs'))
190
+ content.path.should == '/usr/eggs'
191
+ end
192
+
193
+ it "size" do
194
+ content.size.should == 0
195
+ content.update("hjk")
196
+ content.size.should == 3
197
+ end
198
+
199
+ it "each" do
200
+ str = ""
201
+ content.each{|chunk| str << chunk }
202
+ str.should == ""
203
+ content.update("asdf")
204
+ content.each{|chunk| str << chunk }
205
+ str.should == "asdf"
206
+ end
207
+
208
+ end
209
+
210
+ describe "shell commands" do
211
+ let (:content) { Dragonfly::Content.new(app, "big\nstuff", 'name' => 'content.jpg') }
212
+
213
+ it "evalutes using the shell" do
214
+ path = nil
215
+ content.shell_eval do |p|
216
+ path = p
217
+ "cat #{path}"
218
+ end.should == "big\nstuff"
219
+ path.should == app.shell.quote(content.path)
220
+ end
221
+
222
+ it "allows evaluating without escaping" do
223
+ path = nil
224
+ content.shell_eval(:escape => false) do |p|
225
+ path = p
226
+ %{$(echo cat) #{path}}
227
+ end.should == "big\nstuff"
228
+ path.should == content.path
229
+ end
230
+
231
+ it "runs the shell command with a new tempfile path, returning self" do
232
+ original_path = content.path
233
+ old_path = nil
234
+ new_path = nil
235
+ content.shell_update do |o, n|
236
+ old_path = o
237
+ new_path = n
238
+ "cp #{o} #{n}"
239
+ end.should == content
240
+ old_path.should == app.shell.quote(original_path)
241
+ new_path.should == app.shell.quote(content.path)
242
+ content.data.should == "big\nstuff"
243
+ end
244
+
245
+ it "allows updating without escaping" do
246
+ original_path = content.path
247
+ old_path = nil
248
+ new_path = nil
249
+ content.shell_update(:escape => false) do |o, n|
250
+ old_path = o
251
+ new_path = n
252
+ "cat #{o} > #{n}"
253
+ end.should == content
254
+ old_path.should == original_path
255
+ new_path.should == content.path
256
+ content.data.should == "big\nstuff"
257
+ end
258
+
259
+ it "defaults the extension to the same" do
260
+ content.shell_update do |old_path, new_path|
261
+ "cp #{old_path} #{new_path}"
262
+ end
263
+ content.path.should =~ /\.jpg$/
264
+ end
265
+
266
+ it "allows changing the new_path file extension" do
267
+ content.shell_update :ext => 'png' do |old_path, new_path|
268
+ "cp #{old_path} #{new_path}"
269
+ end
270
+ content.path.should =~ /\.png$/
271
+ end
272
+
273
+ describe "generating" do
274
+ let(:content_2) { Dragonfly::Content.new(app) }
275
+
276
+ it "allows generating with the shell" do
277
+ content_2.shell_generate do |path|
278
+ "cp #{content.path} #{path}"
279
+ end.should == content_2
280
+ content_2.data.should == "big\nstuff"
281
+ end
282
+
283
+ it "allows generating without escaping" do
284
+ content_2.shell_generate(:escape => false) do |path|
285
+ "echo dogs >> #{path}"
286
+ end
287
+ content_2.data.should == "dogs\n"
288
+ end
289
+
290
+ it "allows setting the ext on generate" do
291
+ content_2.shell_generate(:ext => 'txt') do |path|
292
+ "cp #{content.path} #{path}"
293
+ end
294
+ content_2.path.should =~ /\.txt$/
295
+ end
296
+ end
297
+
298
+ end
299
+
300
+ describe "store" do
301
+ it "stores itself in the app's datastore" do
302
+ app.datastore.should_receive(:write).with(content, {})
303
+ content.store
304
+ end
305
+
306
+ it "allows passing options" do
307
+ app.datastore.should_receive(:write).with(content, :hello => 'there')
308
+ content.store(:hello => 'there')
309
+ end
310
+ end
311
+
312
+ describe "b64_data" do
313
+ it "returns a b64 data string" do
314
+ content.update("HELLO", "name" => "hello.txt")
315
+ content.b64_data.should == "data:text/plain;base64,SEVMTE8=\n"
316
+ end
317
+ end
318
+
319
+ describe "close" do
320
+ before(:each) do
321
+ @app = test_app
322
+ @app.add_processor(:upcase){|c| c.update("HELLO") }
323
+ @content = Dragonfly::Content.new(@app, "hello")
324
+ @temp_object1 = @content.temp_object
325
+ @content.process!(:upcase)
326
+ @temp_object2 = @content.temp_object
327
+ @temp_object1.should_not == @temp_object2 # just checking
328
+ end
329
+
330
+ it "should clean up tempfiles for the last temp_object" do
331
+ @temp_object2.should_receive(:close)
332
+ @content.close
333
+ end
334
+
335
+ it "should clean up tempfiles for previous temp_objects" do
336
+ @temp_object1.should_receive(:close)
337
+ @content.close
338
+ end
339
+ end
340
+
341
+ describe "env" do
342
+ it "returns the app's env" do
343
+ content.env.should == app.env
344
+ end
345
+ end
346
+
347
+ describe "inspect" do
348
+ it "returns a string" do
349
+ content.inspect.should =~ /Content/
350
+ end
351
+ end
352
+
353
+ end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'rack'
3
+ require 'dragonfly/cookie_monster'
3
4
 
4
5
  describe Dragonfly::CookieMonster do
5
6
 
@@ -19,7 +20,7 @@ describe Dragonfly::CookieMonster do
19
20
  end
20
21
 
21
22
  it "should delete the set-cookie header from the response if the response comes from dragonfly" do
22
- response = Rack::MockRequest.new(app('dragonfly.job' => mock)).get('')
23
+ response = Rack::MockRequest.new(app('dragonfly.job' => double)).get('')
23
24
  response.status.should == 200
24
25
  response.body.should == "body here"
25
26
  response.headers["Set-Cookie"].should be_nil
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+ require 'dragonfly/spec/data_store_examples'
3
+
4
+ describe Dragonfly::FileDataStore do
5
+
6
+ def touch_file(filename)
7
+ FileUtils.mkdir_p(File.dirname(filename))
8
+ FileUtils.touch(filename)
9
+ end
10
+
11
+ def assert_exists(path)
12
+ File.exists?(path).should be_true
13
+ end
14
+
15
+ def assert_does_not_exist(path)
16
+ File.exists?(path).should be_false
17
+ end
18
+
19
+ let (:app) { test_app }
20
+ let (:content) { Dragonfly::Content.new(app, 'goobydoo') }
21
+ let (:new_content) { Dragonfly::Content.new(app) }
22
+
23
+ describe "with a given root path" do
24
+
25
+ before(:each) do
26
+ @data_store = Dragonfly::FileDataStore.new(:root_path => 'tmp/file_data_store_test')
27
+ end
28
+
29
+ after(:each) do
30
+ # Clean up created files
31
+ FileUtils.rm_rf("#{@data_store.root_path}")
32
+ end
33
+
34
+ it_should_behave_like 'data_store'
35
+
36
+ describe "write" do
37
+
38
+ before(:each) do
39
+ # Set 'now' to a date in the past
40
+ Time.stub(:now).and_return Time.mktime(1984,"may",4,14,28,1)
41
+ @file_pattern_prefix_without_root = '1984/05/04/14_28_01_0_'
42
+ @file_pattern_prefix = "#{@data_store.root_path}/#{@file_pattern_prefix_without_root}"
43
+ end
44
+
45
+ it "should store the file in a folder based on date, with default filename" do
46
+ @data_store.write(content)
47
+ assert_exists "#{@file_pattern_prefix}file"
48
+ end
49
+
50
+ it "should use the content name if it exists" do
51
+ content.should_receive(:name).at_least(:once).and_return('hello.there')
52
+ @data_store.write(content)
53
+ assert_exists "#{@file_pattern_prefix}hello.there"
54
+ end
55
+
56
+ it "should get rid of funny characters in the content name" do
57
+ content.should_receive(:name).at_least(:once).and_return('A Picture with many spaces in its name (at 20:00 pm).png')
58
+ @data_store.write(content)
59
+ assert_exists "#{@file_pattern_prefix}A_Picture_with_many_spaces_in_its_name_at_20_00_pm_.png"
60
+ end
61
+
62
+ it "stores meta as YAML" do
63
+ content.meta = {'wassup' => 'doc'}
64
+ @data_store.write(content)
65
+ File.read("#{@file_pattern_prefix}file.meta.yml").should =~ /---\s+wassup: doc/
66
+ end
67
+
68
+ describe "when the filename already exists" do
69
+
70
+ it "should use a different filename" do
71
+ touch_file("#{@file_pattern_prefix}file")
72
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
73
+ @data_store.write(content)
74
+ assert_exists "#{@file_pattern_prefix}file_2"
75
+ end
76
+
77
+ it "should use a different filename taking into account the name and ext" do
78
+ content.should_receive(:name).at_least(:once).and_return('hello.png')
79
+ touch_file("#{@file_pattern_prefix}hello.png")
80
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}hello.png").and_return("#{@file_pattern_prefix}blah.png")
81
+ @data_store.write(content)
82
+ end
83
+
84
+ it "should keep trying until it finds a free filename" do
85
+ touch_file("#{@file_pattern_prefix}file")
86
+ touch_file("#{@file_pattern_prefix}file_2")
87
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
88
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file_2").and_return("#{@file_pattern_prefix}file_3")
89
+ @data_store.write(content)
90
+ assert_exists "#{@file_pattern_prefix}file_3"
91
+ end
92
+
93
+ describe "specifying the uid" do
94
+ it "should allow for specifying the path to use" do
95
+ @data_store.write(content, :path => 'hello/there/mate.png')
96
+ assert_exists "#{@data_store.root_path}/hello/there/mate.png"
97
+ end
98
+ it "should correctly disambiguate if the file exists" do
99
+ touch_file("#{@data_store.root_path}/hello/there/mate.png")
100
+ @data_store.should_receive(:disambiguate).with("#{@data_store.root_path}/hello/there/mate.png").and_return("#{@data_store.root_path}/hello/there/mate_2.png")
101
+ @data_store.write(content, :path => 'hello/there/mate.png')
102
+ assert_exists "#{@data_store.root_path}/hello/there/mate_2.png"
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ describe "return value" do
109
+
110
+ it "should return the filepath without the root of the stored file when a file name is not provided" do
111
+ @data_store.write(content).should == "#{@file_pattern_prefix_without_root}file"
112
+ end
113
+
114
+ it "should return the filepath without the root of the stored file when a file name is provided" do
115
+ content.should_receive(:name).at_least(:once).and_return('hello.you.png')
116
+ @data_store.write(content).should == "#{@file_pattern_prefix_without_root}hello.you.png"
117
+ end
118
+
119
+ end
120
+
121
+ end
122
+
123
+ describe "disambiguate" do
124
+ it "should add a suffix" do
125
+ @data_store.disambiguate('/some/file').should =~ %r{^/some/file_\w+$}
126
+ end
127
+ it "should add a suffix to the basename" do
128
+ @data_store.disambiguate('/some/file.png').should =~ %r{^/some/file_\w+\.png$}
129
+ end
130
+ it "should be random(-ish)" do
131
+ @data_store.disambiguate('/some/file').should_not == @data_store.disambiguate('/some/file')
132
+ end
133
+ end
134
+
135
+ describe "read" do
136
+ it "should be able to read any file, stored or not (and without meta data)" do
137
+ FileUtils.mkdir_p("#{@data_store.root_path}/jelly_beans/are")
138
+ File.open("#{@data_store.root_path}/jelly_beans/are/good", 'w'){|f| f.write('hey dog') }
139
+ new_content.update(*@data_store.read("jelly_beans/are/good"))
140
+ new_content.data.should == 'hey dog'
141
+ new_content.meta.should == {'name' => 'good'}
142
+ end
143
+
144
+ it "should raise if the file path has ../ in it" do
145
+ expect{
146
+ @data_store.read('jelly_beans/../are/good')
147
+ }.to raise_error(Dragonfly::FileDataStore::BadUID)
148
+ end
149
+
150
+ it "should not raise if the file path has .. but not ../ in it" do
151
+ @data_store.write(content, :path => 'jelly_beans..good')
152
+ new_content.update(*@data_store.read('jelly_beans..good'))
153
+ new_content.data.should == 'goobydoo'
154
+ end
155
+ end
156
+
157
+ describe "destroying" do
158
+ it "should prune empty directories when destroying" do
159
+ uid = @data_store.write(content)
160
+ @data_store.destroy(uid)
161
+ @data_store.root_path.should be_an_empty_directory
162
+ end
163
+
164
+ it "should not prune root_path directory when destroying file without directory prefix in path" do
165
+ uid = @data_store.write(content, :path => 'mate.png')
166
+ @data_store.destroy(uid)
167
+ @data_store.root_path.should be_an_empty_directory
168
+ end
169
+
170
+ it "should raise if the file path has ../ in it" do
171
+ expect{
172
+ @data_store.destroy('jelly_beans/../are/good')
173
+ }.to raise_error(Dragonfly::FileDataStore::BadUID)
174
+ end
175
+ end
176
+
177
+ describe "setting the root_path" do
178
+ it "should allow setting as a pathname" do
179
+ @data_store.root_path = Pathname.new('/some/thing')
180
+ @data_store.root_path.should == '/some/thing'
181
+ end
182
+ end
183
+
184
+ describe "relative paths" do
185
+ let(:store) { Dragonfly::FileDataStore.new }
186
+ let(:relative_path) { "2011/02/11/picture.jpg" }
187
+ let(:absolute_path) { "#{root_path}#{relative_path}" }
188
+ let(:root_path) { "/path/to/file/" }
189
+
190
+ before do
191
+ store.root_path = root_path
192
+ end
193
+
194
+ subject { store.send :relative, absolute_path }
195
+
196
+ it { should == relative_path }
197
+
198
+ context "where root path contains spaces" do
199
+ let(:root_path) { "/path/to/file name/" }
200
+ it { should == relative_path }
201
+ end
202
+ context "where root path contains special chars" do
203
+ let(:root_path) { "/path/to/file name (Special backup directory)/" }
204
+ it { should == relative_path }
205
+ end
206
+ end
207
+
208
+ describe "turning meta off" do
209
+ before(:each) do
210
+ @data_store.store_meta = false
211
+ content.meta = {'bitrate' => '35', 'name' => 'danny.boy'}
212
+ end
213
+
214
+ it "should not write a meta file" do
215
+ uid = @data_store.write(content)
216
+ assert_does_not_exist(File.join(@data_store.root_path, "#{uid}.meta"))
217
+ assert_does_not_exist(File.join(@data_store.root_path, "#{uid}.meta.yml"))
218
+ end
219
+
220
+ it "should return an empty hash on read" do
221
+ uid = @data_store.write(content)
222
+ new_content.update(*@data_store.read(uid))
223
+ new_content.meta['bitrate'].should be_nil
224
+ end
225
+
226
+ it "should still destroy the meta file if it exists" do
227
+ @data_store.store_meta = true
228
+ uid = @data_store.write(content)
229
+ @data_store.store_meta = false
230
+ @data_store.destroy(uid)
231
+ @data_store.root_path.should be_an_empty_directory
232
+ end
233
+
234
+ it "should still destroy properly if meta is on but the meta file doesn't exist" do
235
+ uid = @data_store.write(content)
236
+ @data_store.store_meta = true
237
+ @data_store.destroy(uid)
238
+ @data_store.root_path.should be_an_empty_directory
239
+ end
240
+ end
241
+
242
+ describe "urls for serving directly" do
243
+ before(:each) do
244
+ @uid = 'some/path/to/file.png'
245
+ @data_store.root_path = '/var/tmp/eggs'
246
+ end
247
+
248
+ it "should raise an error if called without configuring" do
249
+ expect{
250
+ @data_store.url_for(@uid)
251
+ }.to raise_error(Dragonfly::FileDataStore::UnableToFormUrl)
252
+ end
253
+
254
+ it "should work as expected when the the server root is above the root path" do
255
+ @data_store.server_root = '/var/tmp'
256
+ @data_store.url_for(@uid).should == '/eggs/some/path/to/file.png'
257
+ end
258
+
259
+ it "should work as expected when the the server root is the root path" do
260
+ @data_store.server_root = '/var/tmp/eggs'
261
+ @data_store.url_for(@uid).should == '/some/path/to/file.png'
262
+ end
263
+
264
+ it "should work as expected when the the server root is below the root path" do
265
+ @data_store.server_root = '/var/tmp/eggs/some/path'
266
+ @data_store.url_for(@uid).should == '/to/file.png'
267
+ end
268
+
269
+ it "should allow setting the server_root as a pathname" do
270
+ @data_store.server_root = Pathname.new('/var/tmp/eggs/some/path')
271
+ @data_store.url_for(@uid).should == '/to/file.png'
272
+ end
273
+
274
+ it "should raise an error when the server root doesn't coincide with the root path" do
275
+ @data_store.server_root = '/var/blimey/eggs'
276
+ expect{
277
+ @data_store.url_for(@uid)
278
+ }.to raise_error(Dragonfly::FileDataStore::UnableToFormUrl)
279
+ end
280
+
281
+ it "should raise an error when the server root doesn't coincide with the uid" do
282
+ @data_store.server_root = '/var/tmp/eggs/some/gooney'
283
+ expect{
284
+ @data_store.url_for(@uid)
285
+ }.to raise_error(Dragonfly::FileDataStore::UnableToFormUrl)
286
+ end
287
+ end
288
+
289
+ end
290
+
291
+ describe "deprecated meta" do
292
+ let(:data_store){ Dragonfly::FileDataStore.new(:root_path => 'spec/fixtures/deprecated_stored_content')}
293
+
294
+ it "still works with old-style meta" do
295
+ new_content.update(*data_store.read('eggs.bonus'))
296
+ new_content.data.should == "Barnicle"
297
+ new_content.meta.should == {'name' => 'eggs.bonus', 'some' => 'meta', 'number' => 5}
298
+ end
299
+ end
300
+ end
301
+