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.
- checksums.yaml +7 -0
- data/.gitignore +1 -8
- data/.travis.yml +11 -0
- data/Gemfile +1 -0
- data/History.md +52 -2
- data/LICENSE +1 -1
- data/README.md +38 -95
- data/dev/grid.jpg +0 -0
- data/dev/irbrc.rb +27 -0
- data/dev/rails_template.rb +38 -0
- data/dev/test.ru +56 -0
- data/dev/test_rails +19 -0
- data/dragonfly.gemspec +3 -21
- data/lib/dragonfly.rb +45 -44
- data/lib/dragonfly/app.rb +175 -96
- data/lib/dragonfly/configurable.rb +71 -170
- data/lib/dragonfly/content.rb +211 -0
- data/lib/dragonfly/core_ext/object.rb +1 -6
- data/lib/dragonfly/file_data_store.rb +197 -0
- data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
- data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
- data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
- data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
- data/lib/dragonfly/image_magick/generators/text.rb +127 -0
- data/lib/dragonfly/image_magick/plugin.rb +83 -0
- data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
- data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
- data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
- data/lib/dragonfly/job.rb +118 -134
- data/lib/dragonfly/job_endpoint.rb +2 -0
- data/lib/dragonfly/memory_data_store.rb +34 -0
- data/lib/dragonfly/middleware.rb +5 -3
- data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
- data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
- data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
- data/lib/dragonfly/model/class_methods.rb +109 -0
- data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
- data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
- data/lib/dragonfly/railtie.rb +8 -6
- data/lib/dragonfly/register.rb +27 -0
- data/lib/dragonfly/response.rb +47 -52
- data/lib/dragonfly/routed_endpoint.rb +4 -0
- data/lib/dragonfly/serializer.rb +15 -5
- data/lib/dragonfly/server.rb +56 -29
- data/lib/dragonfly/shell.rb +12 -23
- data/lib/dragonfly/spec/data_store_examples.rb +64 -0
- data/lib/dragonfly/temp_object.rb +32 -47
- data/lib/dragonfly/url_attributes.rb +19 -22
- data/lib/dragonfly/url_mapper.rb +3 -0
- data/lib/dragonfly/utils.rb +12 -0
- data/lib/dragonfly/version.rb +1 -1
- data/lib/dragonfly/whitelist.rb +19 -0
- data/lib/rails/generators/dragonfly/USAGE +8 -0
- data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
- data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
- data/samples/gif.gif +0 -0
- data/spec/dragonfly/app_spec.rb +270 -64
- data/spec/dragonfly/configurable_spec.rb +142 -418
- data/spec/dragonfly/content_spec.rb +353 -0
- data/spec/dragonfly/cookie_monster_spec.rb +2 -1
- data/spec/dragonfly/file_data_store_spec.rb +301 -0
- data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
- data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
- data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
- data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
- data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
- data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
- data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
- data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
- data/spec/dragonfly/job_endpoint_spec.rb +30 -73
- data/spec/dragonfly/job_spec.rb +280 -608
- data/spec/dragonfly/memory_data_store_spec.rb +20 -0
- data/spec/dragonfly/middleware_spec.rb +47 -27
- data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
- data/spec/dragonfly/model/validations_spec.rb +196 -0
- data/spec/dragonfly/register_spec.rb +35 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
- data/spec/dragonfly/serializer_spec.rb +13 -15
- data/spec/dragonfly/server_spec.rb +122 -46
- data/spec/dragonfly/shell_spec.rb +43 -24
- data/spec/dragonfly/temp_object_spec.rb +69 -94
- data/spec/dragonfly/url_attributes_spec.rb +49 -0
- data/spec/dragonfly/utils_spec.rb +32 -0
- data/spec/dragonfly/whitelist_spec.rb +30 -0
- data/spec/dragonfly_spec.rb +43 -0
- data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
- data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
- data/spec/functional/configuration_spec.rb +19 -0
- data/spec/functional/model_urls_spec.rb +43 -41
- data/spec/functional/remote_on_the_fly_spec.rb +14 -16
- data/spec/functional/shell_commands_spec.rb +24 -14
- data/spec/functional/to_response_spec.rb +10 -10
- data/spec/functional/urls_spec.rb +5 -3
- data/spec/spec_helper.rb +23 -28
- data/spec/support/argument_matchers.rb +7 -8
- data/spec/support/image_matchers.rb +14 -36
- data/spec/support/model_helpers.rb +97 -0
- data/spec/support/simple_matchers.rb +12 -0
- metadata +92 -393
- data/.yardopts +0 -29
- data/Rakefile +0 -36
- data/config.ru +0 -14
- data/docs.watchr +0 -1
- data/extra_docs/Analysers.md +0 -68
- data/extra_docs/Caching.md +0 -23
- data/extra_docs/Configuration.md +0 -149
- data/extra_docs/Couch.md +0 -49
- data/extra_docs/DataStorage.md +0 -226
- data/extra_docs/Encoding.md +0 -67
- data/extra_docs/ExampleUseCases.md +0 -116
- data/extra_docs/GeneralUsage.md +0 -105
- data/extra_docs/Generators.md +0 -68
- data/extra_docs/Heroku.md +0 -50
- data/extra_docs/ImageMagick.md +0 -136
- data/extra_docs/Index.md +0 -33
- data/extra_docs/MimeTypes.md +0 -40
- data/extra_docs/Models.md +0 -441
- data/extra_docs/Mongo.md +0 -42
- data/extra_docs/Processing.md +0 -77
- data/extra_docs/Rack.md +0 -52
- data/extra_docs/Rails2.md +0 -57
- data/extra_docs/Rails3.md +0 -56
- data/extra_docs/ServingRemotely.md +0 -104
- data/extra_docs/Sinatra.md +0 -25
- data/extra_docs/URLs.md +0 -203
- data/features/images.feature +0 -47
- data/features/no_processing.feature +0 -14
- data/features/rails.feature +0 -8
- data/features/steps/common_steps.rb +0 -8
- data/features/steps/dragonfly_steps.rb +0 -66
- data/features/steps/rails_steps.rb +0 -40
- data/features/support/env.rb +0 -13
- data/features/support/setup.rb +0 -41
- data/fixtures/rails/files/app/models/album.rb +0 -6
- data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
- data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
- data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
- data/fixtures/rails/files/features/manage_album_images.feature +0 -38
- data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
- data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
- data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
- data/fixtures/rails/files/features/support/paths.rb +0 -17
- data/fixtures/rails/files/features/text_images.feature +0 -7
- data/fixtures/rails/template.rb +0 -20
- data/irbrc.rb +0 -19
- data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
- data/lib/dragonfly/analyser.rb +0 -58
- data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
- data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
- data/lib/dragonfly/config/heroku.rb +0 -26
- data/lib/dragonfly/config/image_magick.rb +0 -6
- data/lib/dragonfly/config/rails.rb +0 -20
- data/lib/dragonfly/data_storage.rb +0 -11
- data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
- data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
- data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
- data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
- data/lib/dragonfly/encoder.rb +0 -13
- data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
- data/lib/dragonfly/function_manager.rb +0 -67
- data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
- data/lib/dragonfly/generator.rb +0 -9
- data/lib/dragonfly/image_magick/analyser.rb +0 -53
- data/lib/dragonfly/image_magick/config.rb +0 -44
- data/lib/dragonfly/image_magick/encoder.rb +0 -57
- data/lib/dragonfly/image_magick/generator.rb +0 -147
- data/lib/dragonfly/image_magick/processor.rb +0 -114
- data/lib/dragonfly/image_magick/utils.rb +0 -46
- data/lib/dragonfly/image_magick_utils.rb +0 -4
- data/lib/dragonfly/job_builder.rb +0 -39
- data/lib/dragonfly/job_definitions.rb +0 -30
- data/lib/dragonfly/loggable.rb +0 -28
- data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
- data/lib/dragonfly/processor.rb +0 -9
- data/lib/dragonfly/rails/images.rb +0 -32
- data/lib/dragonfly/simple_cache.rb +0 -23
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
- data/spec/dragonfly/analyser_spec.rb +0 -123
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
- data/spec/dragonfly/function_manager_spec.rb +0 -154
- data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
- data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
- data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
- data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
- data/spec/dragonfly/job_builder_spec.rb +0 -37
- data/spec/dragonfly/job_definitions_spec.rb +0 -57
- data/spec/dragonfly/loggable_spec.rb +0 -80
- data/spec/dragonfly/simple_cache_spec.rb +0 -27
- data/spec/dragonfly/url_attributes.rb +0 -47
- data/spec/functional/deprecations_spec.rb +0 -51
- data/spec/functional/image_magick_app_spec.rb +0 -27
- data/spec/test_imagemagick.ru +0 -49
- data/yard/handlers/configurable_attr_handler.rb +0 -38
- data/yard/setup.rb +0 -15
- data/yard/templates/default/fulldoc/html/css/common.css +0 -109
- data/yard/templates/default/layout/html/layout.erb +0 -93
- data/yard/templates/default/module/html/configuration_summary.erb +0 -31
- 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' =>
|
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
|
+
|