dragonfly 1.0 → 1.0.1
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -4
- data/History.md +17 -0
- data/README.md +6 -2
- data/Rakefile +1 -0
- data/dragonfly.gemspec +17 -1
- data/lib/dragonfly/app.rb +10 -1
- data/lib/dragonfly/file_data_store.rb +1 -1
- data/lib/dragonfly/image_magick/plugin.rb +3 -2
- data/lib/dragonfly/job.rb +5 -178
- data/lib/dragonfly/job/fetch.rb +19 -0
- data/lib/dragonfly/job/fetch_file.rb +27 -0
- data/lib/dragonfly/job/fetch_url.rb +75 -0
- data/lib/dragonfly/job/generate.rb +27 -0
- data/lib/dragonfly/job/process.rb +27 -0
- data/lib/dragonfly/job/step.rb +44 -0
- data/lib/dragonfly/model/attachment.rb +0 -2
- data/lib/dragonfly/model/class_methods.rb +5 -0
- data/lib/dragonfly/rails/images.rb +1 -0
- data/lib/dragonfly/response.rb +11 -2
- data/lib/dragonfly/routed_endpoint.rb +15 -5
- data/lib/dragonfly/serializer.rb +2 -2
- data/lib/dragonfly/shell.rb +28 -5
- data/lib/dragonfly/version.rb +1 -1
- data/spec/dragonfly/file_data_store_spec.rb +29 -32
- data/spec/dragonfly/job/fetch_file_spec.rb +26 -0
- data/spec/dragonfly/job/fetch_spec.rb +26 -0
- data/spec/dragonfly/job/fetch_url_spec.rb +123 -0
- data/spec/dragonfly/job/generate_spec.rb +28 -0
- data/spec/dragonfly/job/process_spec.rb +28 -0
- data/spec/dragonfly/job_endpoint_spec.rb +17 -0
- data/spec/dragonfly/job_spec.rb +0 -187
- data/spec/dragonfly/model/model_spec.rb +27 -12
- data/spec/dragonfly/routed_endpoint_spec.rb +69 -28
- data/spec/dragonfly/shell_spec.rb +2 -2
- data/spec/support/simple_matchers.rb +1 -1
- metadata +43 -16
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Job::Generate do
|
4
|
+
|
5
|
+
let (:app) { test_app }
|
6
|
+
let (:job) { Dragonfly::Job.new(app) }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
app.add_generator(:plasma){}
|
10
|
+
end
|
11
|
+
|
12
|
+
it "adds a step" do
|
13
|
+
job.generate!(:plasma, 20)
|
14
|
+
job.steps.should match_steps([Dragonfly::Job::Generate])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "uses the generator when applied" do
|
18
|
+
job.generate!(:plasma, 20)
|
19
|
+
app.get_generator(:plasma).should_receive(:call).with(job.content, 20)
|
20
|
+
job.apply
|
21
|
+
end
|
22
|
+
|
23
|
+
it "updates the url if method exists" do
|
24
|
+
app.get_generator(:plasma).should_receive(:update_url).with(job.url_attributes, 20)
|
25
|
+
job.generate!(:plasma, 20)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dragonfly::Job::Process do
|
4
|
+
|
5
|
+
let (:app) { test_app }
|
6
|
+
let (:job) { Dragonfly::Job.new(app) }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
app.add_processor(:resize){}
|
10
|
+
end
|
11
|
+
|
12
|
+
it "adds a step" do
|
13
|
+
job.process!(:resize, '20x30')
|
14
|
+
job.steps.should match_steps([Dragonfly::Job::Process])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should use the processor when applied" do
|
18
|
+
job.process!(:resize, '20x30')
|
19
|
+
app.get_processor(:resize).should_receive(:call).with(job.content, '20x30')
|
20
|
+
job.apply
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should call update_url immediately with the url_attributes" do
|
24
|
+
app.get_processor(:resize).should_receive(:update_url).with(job.url_attributes, '20x30')
|
25
|
+
job.process!(:resize, '20x30')
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -94,6 +94,23 @@ describe Dragonfly::JobEndpoint do
|
|
94
94
|
response.status.should == 500
|
95
95
|
end
|
96
96
|
|
97
|
+
describe "default content disposition file name" do
|
98
|
+
before do
|
99
|
+
uid = @app.store("GUNGLE", 'name' => 'güng.txt')
|
100
|
+
@job = @app.fetch(uid)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "doesn't encode utf8 characters" do
|
104
|
+
response = make_request(@job)
|
105
|
+
response['Content-Disposition'].should == 'filename="güng.txt"'
|
106
|
+
end
|
107
|
+
|
108
|
+
it "does encode them if the request is from IE" do
|
109
|
+
response = make_request(@job, 'HTTP_USER_AGENT' => "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; el-GR)")
|
110
|
+
response['Content-Disposition'].should == 'filename="g%C3%BCng.txt"'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
97
114
|
describe "logging" do
|
98
115
|
it "logs successful requests" do
|
99
116
|
Dragonfly.should_receive(:info).with("GET /something?great 200")
|
data/spec/dragonfly/job_spec.rb
CHANGED
@@ -53,199 +53,12 @@ describe Dragonfly::Job do
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
describe "fetch" do
|
57
|
-
before(:each) do
|
58
|
-
job.fetch!('some_uid')
|
59
|
-
end
|
60
|
-
|
61
|
-
it { job.steps.should match_steps([Dragonfly::Job::Fetch]) }
|
62
|
-
|
63
|
-
it "should read from the app's datastore when applied" do
|
64
|
-
app.datastore.should_receive(:read).with('some_uid').and_return ["", {}]
|
65
|
-
job.apply
|
66
|
-
end
|
67
|
-
|
68
|
-
it "raises NotFound if the datastore returns nil" do
|
69
|
-
app.datastore.should_receive(:read).and_return(nil)
|
70
|
-
expect {
|
71
|
-
job.apply
|
72
|
-
}.to raise_error(Dragonfly::Job::Fetch::NotFound)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe "generate" do
|
77
|
-
before :each do
|
78
|
-
app.add_generator(:plasma){}
|
79
|
-
end
|
80
|
-
|
81
|
-
it "adds a step" do
|
82
|
-
job.generate!(:plasma, 20)
|
83
|
-
job.steps.should match_steps([Dragonfly::Job::Generate])
|
84
|
-
end
|
85
|
-
|
86
|
-
it "uses the generator when applied" do
|
87
|
-
job.generate!(:plasma, 20)
|
88
|
-
app.get_generator(:plasma).should_receive(:call).with(job.content, 20)
|
89
|
-
job.apply
|
90
|
-
end
|
91
|
-
|
92
|
-
it "updates the url if method exists" do
|
93
|
-
app.get_generator(:plasma).should_receive(:update_url).with(job.url_attributes, 20)
|
94
|
-
job.generate!(:plasma, 20)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
describe "fetch_file" do
|
99
|
-
before(:each) do
|
100
|
-
job.fetch_file!(File.dirname(__FILE__) + '/../../samples/egg.png')
|
101
|
-
end
|
102
|
-
|
103
|
-
it { job.steps.should match_steps([Dragonfly::Job::FetchFile]) }
|
104
|
-
|
105
|
-
it "should fetch the specified file when applied" do
|
106
|
-
job.size.should == 62664
|
107
|
-
end
|
108
|
-
|
109
|
-
it "should set the url_attributes" do
|
110
|
-
job.url_attributes.name.should == 'egg.png'
|
111
|
-
end
|
112
|
-
|
113
|
-
it "should set the name" do
|
114
|
-
job.name.should == 'egg.png'
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe "fetch_url" do
|
119
|
-
before(:each) do
|
120
|
-
stub_request(:get, %r{http://place\.com/.*}).to_return(:body => 'result!')
|
121
|
-
end
|
122
|
-
|
123
|
-
it "adds a step" do
|
124
|
-
job.fetch_url!('some.url')
|
125
|
-
job.steps.should match_steps([Dragonfly::Job::FetchUrl])
|
126
|
-
end
|
127
|
-
|
128
|
-
it "should fetch the specified url when applied" do
|
129
|
-
job.fetch_url!('http://place.com')
|
130
|
-
job.data.should == "result!"
|
131
|
-
end
|
132
|
-
|
133
|
-
it "should default to http" do
|
134
|
-
job.fetch_url!('place.com')
|
135
|
-
job.data.should == "result!"
|
136
|
-
end
|
137
|
-
|
138
|
-
it "should also work with https" do
|
139
|
-
stub_request(:get, 'https://place.com').to_return(:body => 'secure result!')
|
140
|
-
job.fetch_url!('https://place.com')
|
141
|
-
job.data.should == "secure result!"
|
142
|
-
end
|
143
|
-
|
144
|
-
[
|
145
|
-
"place.com",
|
146
|
-
"http://place.com",
|
147
|
-
"place.com/",
|
148
|
-
"place.com/stuff/",
|
149
|
-
"place.com/?things"
|
150
|
-
].each do |url|
|
151
|
-
it "doesn't set the name if there isn't one, e.g. for #{url}" do
|
152
|
-
job.fetch_url!(url)
|
153
|
-
job.name.should be_nil
|
154
|
-
end
|
155
|
-
|
156
|
-
it "doesn't set the name url_attr if there isn't one, e.g. for #{url}" do
|
157
|
-
job.fetch_url!(url)
|
158
|
-
job.url_attributes.name.should be_nil
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
[
|
163
|
-
"place.com/dung.beetle",
|
164
|
-
"http://place.com/dung.beetle",
|
165
|
-
"place.com/stuff/dung.beetle",
|
166
|
-
"place.com/dung.beetle?morethings"
|
167
|
-
].each do |url|
|
168
|
-
it "sets the name if there is one, e.g. for #{url}" do
|
169
|
-
job.fetch_url!(url)
|
170
|
-
job.name.should == 'dung.beetle'
|
171
|
-
end
|
172
|
-
|
173
|
-
it "sets the name url_attr if there is one, e.g. for #{url}" do
|
174
|
-
job.fetch_url!(url)
|
175
|
-
job.url_attributes.name.should == 'dung.beetle'
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
it "should raise an error if not found" do
|
180
|
-
stub_request(:get, "notfound.com").to_return(:status => 404, :body => "BLAH")
|
181
|
-
expect{
|
182
|
-
job.fetch_url!('notfound.com').apply
|
183
|
-
}.to raise_error(Dragonfly::Job::FetchUrl::ErrorResponse){|error|
|
184
|
-
error.status.should == 404
|
185
|
-
error.body.should == "BLAH"
|
186
|
-
}
|
187
|
-
end
|
188
|
-
|
189
|
-
it "should raise an error if server error" do
|
190
|
-
stub_request(:get, "error.com").to_return(:status => 500, :body => "BLAH")
|
191
|
-
expect{
|
192
|
-
job.fetch_url!('error.com').apply
|
193
|
-
}.to raise_error(Dragonfly::Job::FetchUrl::ErrorResponse){|error|
|
194
|
-
error.status.should == 500
|
195
|
-
error.body.should == "BLAH"
|
196
|
-
}
|
197
|
-
end
|
198
|
-
|
199
|
-
it "should follow redirects" do
|
200
|
-
stub_request(:get, "redirectme.com").to_return(:status => 302, :headers => {'Location' => 'http://ok.com'})
|
201
|
-
stub_request(:get, "ok.com").to_return(:body => "OK!")
|
202
|
-
job.fetch_url('redirectme.com').data.should == 'OK!'
|
203
|
-
end
|
204
|
-
|
205
|
-
describe "data uris" do
|
206
|
-
it "accepts standard base64 encoded data uris" do
|
207
|
-
job.fetch_url!("data:text/plain;base64,aGVsbG8=\n")
|
208
|
-
job.data.should == 'hello'
|
209
|
-
job.mime_type.should == 'text/plain'
|
210
|
-
job.ext.should == 'txt'
|
211
|
-
end
|
212
|
-
|
213
|
-
it "doesn't accept other data uris" do
|
214
|
-
expect {
|
215
|
-
job.fetch_url!("data:text/html;charset=utf-8,<stuff />").apply
|
216
|
-
}.to raise_error(Dragonfly::Job::FetchUrl::CannotHandle)
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
56
|
describe "apply" do
|
222
57
|
it "should return itself" do
|
223
58
|
job.apply.should == job
|
224
59
|
end
|
225
60
|
end
|
226
61
|
|
227
|
-
describe "process" do
|
228
|
-
before :each do
|
229
|
-
app.add_processor(:resize){}
|
230
|
-
end
|
231
|
-
|
232
|
-
it "adds a step" do
|
233
|
-
job.process!(:resize, '20x30')
|
234
|
-
job.steps.should match_steps([Dragonfly::Job::Process])
|
235
|
-
end
|
236
|
-
|
237
|
-
it "should use the processor when applied" do
|
238
|
-
job.process!(:resize, '20x30')
|
239
|
-
app.get_processor(:resize).should_receive(:call).with(job.content, '20x30')
|
240
|
-
job.apply
|
241
|
-
end
|
242
|
-
|
243
|
-
it "should call update_url immediately with the url_attributes" do
|
244
|
-
app.get_processor(:resize).should_receive(:update_url).with(job.url_attributes, '20x30')
|
245
|
-
job.process!(:resize, '20x30')
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
62
|
describe "analysis" do
|
250
63
|
let (:job) { Dragonfly::Job.new(app, "HELLO") }
|
251
64
|
|
@@ -946,7 +946,7 @@ describe "models" do
|
|
946
946
|
end
|
947
947
|
end
|
948
948
|
|
949
|
-
describe "
|
949
|
+
describe "xxx_changed?" do
|
950
950
|
before(:each) do
|
951
951
|
@item_class = new_model_class('Item', :preview_image_uid) do
|
952
952
|
dragonfly_accessor :preview_image
|
@@ -955,21 +955,36 @@ describe "models" do
|
|
955
955
|
end
|
956
956
|
|
957
957
|
it "should be changed when assigned" do
|
958
|
+
expect( @item.preview_image_changed? ).to be_false
|
958
959
|
@item.preview_image = 'ggg'
|
959
|
-
@item.
|
960
|
+
expect( @item.preview_image_changed? ).to be_true
|
960
961
|
end
|
961
962
|
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
963
|
+
describe "after saving" do
|
964
|
+
before do
|
965
|
+
@item.preview_image = 'ggg'
|
966
|
+
@item.save!
|
967
|
+
end
|
968
|
+
|
969
|
+
it "should not be changed" do
|
970
|
+
expect( @item.preview_image_changed? ).to be_false
|
971
|
+
end
|
972
|
+
|
973
|
+
it "should be changed when set to nil" do
|
974
|
+
@item.preview_image = nil
|
975
|
+
expect( @item.preview_image_changed? ).to be_true
|
976
|
+
end
|
977
|
+
|
978
|
+
it "should be changed when changed" do
|
979
|
+
@item.preview_image = "asdf"
|
980
|
+
expect( @item.preview_image_changed? ).to be_true
|
981
|
+
end
|
982
|
+
|
983
|
+
it "should not be changed when reloaded" do
|
984
|
+
item = @item_class.find(@item.id)
|
985
|
+
expect( @item.preview_image_changed? ).to be_false
|
986
|
+
end
|
967
987
|
|
968
|
-
it "should not be changed when reloaded" do
|
969
|
-
@item.preview_image = 'ggg'
|
970
|
-
@item.save!
|
971
|
-
item = @item_class.find(@item.id)
|
972
|
-
item.preview_image.should_not be_changed
|
973
988
|
end
|
974
989
|
end
|
975
990
|
|
@@ -10,43 +10,84 @@ describe Dragonfly::RoutedEndpoint do
|
|
10
10
|
Rack::MockRequest.env_for(url, opts)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
let (:app) { test_app }
|
14
|
+
|
15
|
+
describe "endpoint returning a job" do
|
16
|
+
let (:endpoint) {
|
17
|
+
Dragonfly::RoutedEndpoint.new(app) {|params, app|
|
18
|
+
app.fetch(params[:uid])
|
19
|
+
}
|
17
20
|
}
|
18
|
-
@uid = @app.store('wassup')
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
before(:each) do
|
23
|
+
@uid = app.store('wassup')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise an error when there are no routing parameters" do
|
27
|
+
lambda{
|
28
|
+
endpoint.call(env_for('/blah'))
|
29
|
+
}.should raise_error(Dragonfly::RoutedEndpoint::NoRoutingParams)
|
30
|
+
end
|
31
|
+
|
32
|
+
{
|
33
|
+
'Rails' => 'action_dispatch.request.path_parameters',
|
34
|
+
'HTTP Router' => 'router.params',
|
35
|
+
'Rack-Mount' => 'rack.routing_args',
|
36
|
+
'Dragonfly' => 'dragonfly.params'
|
37
|
+
}.each do |name, key|
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
'Rack-Mount' => 'rack.routing_args',
|
32
|
-
'Dragonfly' => 'dragonfly.params'
|
33
|
-
}.each do |name, key|
|
39
|
+
it "should work with #{name} routing args" do
|
40
|
+
response = response_for endpoint.call(env_for('/blah', key => {:uid => @uid}))
|
41
|
+
response.body.should == 'wassup'
|
42
|
+
end
|
34
43
|
|
35
|
-
|
36
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should merge with query parameters" do
|
47
|
+
env = Rack::MockRequest.env_for("/big/buns?uid=#{@uid}", 'dragonfly.params' => {:something => 'else'})
|
48
|
+
response = response_for endpoint.call(env)
|
37
49
|
response.body.should == 'wassup'
|
38
50
|
end
|
39
51
|
|
52
|
+
it "should have nice inspect output" do
|
53
|
+
endpoint.inspect.should =~ /<Dragonfly::RoutedEndpoint for app :default >/
|
54
|
+
end
|
40
55
|
end
|
41
56
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
57
|
+
describe "endpoint returning other things" do
|
58
|
+
let (:model_class) {
|
59
|
+
Class.new do
|
60
|
+
extend Dragonfly::Model
|
61
|
+
dragonfly_accessor :image
|
62
|
+
attr_accessor :image_uid
|
63
|
+
end
|
64
|
+
}
|
65
|
+
let (:model) {
|
66
|
+
model_class.new
|
67
|
+
}
|
68
|
+
let (:endpoint) {
|
69
|
+
Dragonfly::RoutedEndpoint.new(app) {|params, app|
|
70
|
+
model.image
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
it "acts like the job one" do
|
75
|
+
model.image = "wassup"
|
76
|
+
response = response_for endpoint.call(env_for('/blah', 'dragonfly.params' => {}))
|
77
|
+
response.body.should == 'wassup'
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns 404 if nil is returned from the endpoint" do
|
81
|
+
endpoint = Dragonfly::RoutedEndpoint.new(app) { nil }
|
82
|
+
response = response_for endpoint.call(env_for('/blah', 'dragonfly.params' => {}))
|
83
|
+
response.status.should == 404
|
84
|
+
end
|
47
85
|
|
48
|
-
|
49
|
-
|
50
|
-
|
86
|
+
it "returns 500 if something else is returned from the endpoint" do
|
87
|
+
endpoint = Dragonfly::RoutedEndpoint.new(app) { "ASDF" }
|
88
|
+
response = response_for endpoint.call(env_for('/blah', 'dragonfly.params' => {}))
|
89
|
+
response.status.should == 500
|
90
|
+
end
|
91
|
+
end
|
51
92
|
|
52
93
|
end
|