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
@@ -6,7 +6,7 @@ require 'spec_helper'
6
6
  describe "Dragonfly::JobEndpoint Rack::Lint tests" do
7
7
  before(:each) do
8
8
  @app = test_app
9
- @app.generator.add(:test_data){ "Test Data" }
9
+ @app.add_generator(:test_data){|content| content.update("Test Data") }
10
10
  @job = @app.generate(:test_data)
11
11
  @endpoint = Rack::Lint.new(Dragonfly::JobEndpoint.new(@job))
12
12
  end
@@ -37,13 +37,14 @@ describe Dragonfly::JobEndpoint do
37
37
  def make_request(job, opts={})
38
38
  endpoint = Dragonfly::JobEndpoint.new(job)
39
39
  method = (opts.delete(:method) || :get).to_s.upcase
40
- Rack::MockRequest.new(endpoint).request(method, '', opts)
40
+ uri = opts[:path] || ""
41
+ Rack::MockRequest.new(endpoint).request(method, uri, opts)
41
42
  end
42
43
 
43
44
  before(:each) do
44
45
  @app = test_app
45
- @app.datastore.stub!(:retrieve).with('egg').and_return(["GUNGLE", {:name => 'gung.txt'}])
46
- @job = @app.new_job.fetch('egg')
46
+ uid = @app.store("GUNGLE", 'name' => 'gung.txt')
47
+ @job = @app.fetch(uid)
47
48
  end
48
49
 
49
50
  it "should return a correct response to a successful GET request" do
@@ -75,21 +76,29 @@ describe Dragonfly::JobEndpoint do
75
76
  response.status.should == 405
76
77
  response['Allow'].should == "GET, HEAD"
77
78
  response['Content-Type'].should == 'text/plain'
78
- response.body.should == "#{method} method not allowed"
79
+ response.body.should == "method not allowed"
79
80
  end
80
81
 
81
82
  end
82
83
 
83
- it "should return 404 if the datastore raises data not found" do
84
- @job.should_receive(:apply).and_raise(Dragonfly::DataStorage::DataNotFound)
84
+ it "should return 404 if the datastore raises NotFound" do
85
+ @job.should_receive(:apply).and_raise(Dragonfly::Job::Fetch::NotFound)
85
86
  response = make_request(@job)
86
87
  response.status.should == 404
87
88
  end
88
89
 
89
- it "should return a 404 if the datastore raises bad uid" do
90
- @job.should_receive(:apply).and_raise(Dragonfly::DataStorage::BadUID)
90
+ it "returns a 500 for any runtime error" do
91
+ @job.should_receive(:apply).and_raise(RuntimeError, "oh dear")
92
+ Dragonfly.should_receive(:warn).with(/oh dear/)
91
93
  response = make_request(@job)
92
- response.status.should == 404
94
+ response.status.should == 500
95
+ end
96
+
97
+ describe "logging" do
98
+ it "logs successful requests" do
99
+ Dragonfly.should_receive(:info).with("GET /something?great 200")
100
+ make_request(@job, :path => '/something?great')
101
+ end
93
102
  end
94
103
 
95
104
  describe "ETag" do
@@ -105,7 +114,7 @@ describe Dragonfly::JobEndpoint do
105
114
  '*'
106
115
  ].each do |header|
107
116
  it "should return a 304 if the correct ETag is specified in HTTP_IF_NONE_MATCH header e.g. #{header}" do
108
- @job.should_receive(:unique_signature).at_least(:once).and_return('dingle')
117
+ @job.should_receive(:signature).at_least(:once).and_return('dingle')
109
118
  response = make_request(@job, 'HTTP_IF_NONE_MATCH' => header)
110
119
  response.status.should == 304
111
120
  response['ETag'].should == '"dingle"'
@@ -115,70 +124,14 @@ describe Dragonfly::JobEndpoint do
115
124
  end
116
125
 
117
126
  it "should not have applied any steps if the correct ETag is specified in HTTP_IF_NONE_MATCH header" do
118
- response = make_request(@job, 'HTTP_IF_NONE_MATCH' => @job.unique_signature)
127
+ response = make_request(@job, 'HTTP_IF_NONE_MATCH' => @job.signature)
119
128
  @job.applied_steps.should be_empty
120
129
  end
121
130
  end
122
131
 
123
- describe "Content Disposition" do
124
- before(:each) do
125
- @app.encoder.add{|temp_object, format| temp_object }
126
- end
127
-
128
- describe "filename" do
129
- it "should return the original name" do
130
- response = make_request(@job)
131
- response['Content-Disposition'].should == 'filename="gung.txt"'
132
- end
133
- it "should return a filename with a different extension if it's been encoded" do
134
- response = make_request(@job.encode(:doogs))
135
- response['Content-Disposition'].should == 'filename="gung.doogs"'
136
- end
137
- it "should not have the filename if name doesn't exist" do
138
- response = make_request(@app.new_job("ADFSDF"))
139
- response['Content-Disposition'].should be_nil
140
- end
141
- it "should cope with filenames with no ext" do
142
- response = make_request(@app.new_job("ASDF", :name => 'asdf'))
143
- response['Content-Disposition'].should == 'filename="asdf"'
144
- end
145
- it "should uri encode funny characters" do
146
- response = make_request(@app.new_job("ASDF", :name => '£@$£ `'))
147
- response['Content-Disposition'].should == 'filename="%C2%A3@$%C2%A3%20%60"'
148
- end
149
- it "should allow for setting the filename using a block" do
150
- @app.content_filename = proc{|job, request|
151
- job.basename.reverse.upcase + request['a']
152
- }
153
- response = make_request(@job, 'QUERY_STRING' => 'a=egg')
154
- response['Content-Disposition'].should == 'filename="GNUGegg"'
155
- end
156
- it "should not include the filename if configured to be nil" do
157
- @app.content_filename = nil
158
- response = make_request(@job)
159
- response['Content-Disposition'].should be_nil
160
- end
161
- end
162
-
163
- describe "content disposition" do
164
- it "should use the app's configured content-disposition" do
165
- @app.content_disposition = :attachment
166
- response = make_request(@job)
167
- response['Content-Disposition'].should == 'attachment; filename="gung.txt"'
168
- end
169
- it "should allow using a block to set the content disposition" do
170
- @app.content_disposition = proc{|job, request|
171
- job.basename + request['blah']
172
- }
173
- response = make_request(@job, 'QUERY_STRING' => 'blah=yo')
174
- response['Content-Disposition'].should == 'gungyo; filename="gung.txt"'
175
- end
176
- end
177
- end
178
-
179
132
  describe "custom headers" do
180
133
  before(:each) do
181
- @app.configure{|c| c.response_headers['This-is'] = 'brill' }
134
+ @app.configure{ response_header 'This-is', 'brill' }
182
135
  end
183
136
  it "should allow specifying custom headers" do
184
137
  make_request(@job).headers['This-is'].should == 'brill'
@@ -191,17 +144,21 @@ describe Dragonfly::JobEndpoint do
191
144
  make_request(@job).headers['Cache-Control'].should == 'try me'
192
145
  end
193
146
  it "should allow giving a proc" do
194
- @app.response_headers['Cache-Control'] = proc{|job, request|
195
- job.basename.reverse.upcase + request['a']
147
+ @app.response_headers['Cache-Control'] = proc{|job, request, headers|
148
+ [job.basename.reverse.upcase, request['a'], headers['Cache-Control'].chars.first].join(',')
196
149
  }
197
150
  response = make_request(@job, 'QUERY_STRING' => 'a=egg')
198
- response['Cache-Control'].should == 'GNUGegg'
151
+ response['Cache-Control'].should == 'GNUG,egg,p'
152
+ end
153
+ it "should allow removing by setting to nil" do
154
+ @app.response_headers['Cache-Control'] = nil
155
+ make_request(@job).headers.should_not have_key('Cache-Control')
199
156
  end
200
157
  end
201
158
 
202
159
  describe "setting the job in the env for communicating with other rack middlewares" do
203
160
  before(:each) do
204
- @app.generator.add(:test_data){ "TEST DATA" }
161
+ @app.add_generator(:test_data){ "TEST DATA" }
205
162
  @job = @app.generate(:test_data)
206
163
  @endpoint = Dragonfly::JobEndpoint.new(@job)
207
164
  @middleware = Class.new do
@@ -1,12 +1,6 @@
1
+ # encoding: UTF-8
1
2
  require 'spec_helper'
2
3
 
3
- # Matchers
4
- RSpec::Matchers.define :match_steps do |steps|
5
- match do |given|
6
- given.map{|step| step.class } == steps
7
- end
8
- end
9
-
10
4
  describe Dragonfly::Job do
11
5
 
12
6
  describe "Step types" do
@@ -14,7 +8,6 @@ describe Dragonfly::Job do
14
8
  {
15
9
  Dragonfly::Job::Fetch => :fetch,
16
10
  Dragonfly::Job::Process => :process,
17
- Dragonfly::Job::Encode => :encode,
18
11
  Dragonfly::Job::Generate => :generate,
19
12
  Dragonfly::Job::FetchFile => :fetch_file,
20
13
  Dragonfly::Job::FetchUrl => :fetch_url
@@ -27,7 +20,6 @@ describe Dragonfly::Job do
27
20
  {
28
21
  Dragonfly::Job::Fetch => 'f',
29
22
  Dragonfly::Job::Process => 'p',
30
- Dragonfly::Job::Encode => 'e',
31
23
  Dragonfly::Job::Generate => 'g',
32
24
  Dragonfly::Job::FetchFile => 'ff',
33
25
  Dragonfly::Job::FetchUrl => 'fu'
@@ -39,294 +31,245 @@ describe Dragonfly::Job do
39
31
 
40
32
  describe "step_names" do
41
33
  it "should return the available step names" do
42
- Dragonfly::Job.step_names.should == [:fetch, :process, :encode, :generate, :fetch_file, :fetch_url]
34
+ Dragonfly::Job.step_names.should == [:fetch, :process, :generate, :fetch_file, :fetch_url]
43
35
  end
44
36
  end
45
37
 
46
38
  end
47
39
 
48
- it "should allow initializing with content" do
49
- job = Dragonfly::Job.new(@app, 'eggheads')
40
+ let (:app) { test_app }
41
+ let (:job) { Dragonfly::Job.new(app) }
42
+
43
+ it "allows initializing with content" do
44
+ job = Dragonfly::Job.new(app, 'eggheads')
50
45
  job.data.should == 'eggheads'
51
46
  end
52
47
 
53
- describe "without content" do
48
+ describe "content" do
49
+ it "starts with an empty content" do
50
+ job.content.should be_a(Dragonfly::Content)
51
+ job.content.data.should == ""
52
+ job.content.meta.should == {}
53
+ end
54
+ end
54
55
 
56
+ describe "fetch" do
55
57
  before(:each) do
56
- @app = test_app
57
- @job = Dragonfly::Job.new(@app)
58
+ job.fetch!('some_uid')
58
59
  end
59
60
 
60
- describe "fetch" do
61
- before(:each) do
62
- @job.fetch!('some_uid')
63
- end
64
-
65
- it { @job.steps.should match_steps([Dragonfly::Job::Fetch]) }
66
-
67
- it "should retrieve from the app's datastore when applied" do
68
- @app.datastore.should_receive(:retrieve).with('some_uid').and_return('HELLO')
69
- @job.data.should == 'HELLO'
70
- end
71
-
72
- it "should set extra data if returned from the datastore" do
73
- @app.datastore.should_receive(:retrieve).with('some_uid').and_return(['HELLO', {:name => 'test.txt'}])
74
- @job.data.should == 'HELLO'
75
- @job.meta.should == {:name => 'test.txt'}
76
- end
61
+ it { job.steps.should match_steps([Dragonfly::Job::Fetch]) }
77
62
 
78
- it "shouldn't set any url_attrs" do
79
- @job.url_attrs.should == {}
80
- end
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
81
66
  end
82
67
 
83
- describe "process" do
84
- it "should raise an error when applying" do
85
- @job.process!(:resize, '20x30')
86
- lambda{
87
- @job.apply
88
- }.should raise_error(Dragonfly::Job::NothingToProcess)
89
- end
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)
90
73
  end
74
+ end
91
75
 
92
- describe "encode" do
93
- it "should raise an error when applying" do
94
- @job.encode!(:gif)
95
- lambda{
96
- @job.apply
97
- }.should raise_error(Dragonfly::Job::NothingToEncode)
98
- end
76
+ describe "generate" do
77
+ before :each do
78
+ app.add_generator(:plasma){}
99
79
  end
100
80
 
101
- describe "analyse" do
102
- it "should raise a NoContent error" do
103
- job = @app.new_job # This will define #analyser on it
104
- lambda{
105
- job.analyse(:width)
106
- }.should raise_error(Dragonfly::Job::NoContent)
107
- end
81
+ it "adds a step" do
82
+ job.generate!(:plasma, 20)
83
+ job.steps.should match_steps([Dragonfly::Job::Generate])
108
84
  end
109
85
 
110
- describe "data" do
111
- it "should raise a NoContent error" do
112
- lambda{
113
- @job.data
114
- }.should raise_error(Dragonfly::Job::NoContent)
115
- end
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
116
90
  end
117
91
 
118
- describe "generate" do
119
- before(:each) do
120
- @job.generate!(:plasma, 20, 30)
121
- end
122
-
123
- it { @job.steps.should match_steps([Dragonfly::Job::Generate]) }
124
-
125
- it "should use the generator when applied" do
126
- @app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return('hi')
127
- @job.data.should == 'hi'
128
- end
129
-
130
- it "should save extra data if the generator returns it" do
131
- @app.generator.should_receive(:generate).with(:plasma, 20, 30).and_return(['hi', {:name => 'plasma.png'}])
132
- @job.data.should == 'hi'
133
- @job.meta.should == {:name => 'plasma.png'}
134
- end
135
-
136
- it "shouldn't set any url_attrs" do
137
- @job.url_attrs.should == {}
138
- end
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)
139
95
  end
96
+ end
140
97
 
141
- describe "fetch_file" do
142
- before(:each) do
143
- @job.fetch_file!(File.dirname(__FILE__) + '/../../samples/egg.png')
144
- end
145
-
146
- it { @job.steps.should match_steps([Dragonfly::Job::FetchFile]) }
147
-
148
- it "should fetch the specified file when applied" do
149
- @job.size.should == 62664
150
- end
151
-
152
- it "should set the url_attrs" do
153
- @job.url_attrs.should == {:name => 'egg.png'}
154
- end
155
-
156
- it "should set the name" do
157
- @job.meta[:name].should == 'egg.png'
158
- end
98
+ describe "fetch_file" do
99
+ before(:each) do
100
+ job.fetch_file!(File.dirname(__FILE__) + '/../../samples/egg.png')
159
101
  end
160
102
 
161
- describe "fetch_url" do
162
- before(:each) do
163
- stub_request(:get, %r{http://some\.place\.com/.*}).to_return(:body => 'result!')
164
- stub_request(:get, 'https://some.place.com').to_return(:body => 'secure result!')
165
- end
166
-
167
- it {
168
- @job.fetch_url!('some.url')
169
- @job.steps.should match_steps([Dragonfly::Job::FetchUrl])
170
- }
171
-
172
- it "should fetch the specified url when applied" do
173
- @job.fetch_url!('http://some.place.com')
174
- @job.data.should == "result!"
175
- end
103
+ it { job.steps.should match_steps([Dragonfly::Job::FetchFile]) }
176
104
 
177
- it "should default to http" do
178
- @job.fetch_url!('some.place.com')
179
- @job.data.should == "result!"
180
- end
181
-
182
- it "should also work with https" do
183
- @job.fetch_url!('https://some.place.com')
184
- @job.data.should == "secure result!"
185
- end
186
-
187
- it "should set the name if there is one" do
188
- @job.fetch_url!('some.place.com/dung.beetle')
189
- @job.meta[:name].should == 'dung.beetle'
190
- end
191
-
192
- it "should set the name url_attr if there is one" do
193
- @job.fetch_url!('some.place.com/dung.beetle')
194
- @job.url_attrs.should == {:name =>'dung.beetle'}
195
- end
196
-
197
- ["some.place.com", "some.place.com/", "some.place.com/eggs/"].each do |url|
198
- it "should not set the name if there isn't one, e.g. #{url}" do
199
- @job.fetch_url!(url)
200
- @job.meta[:name].should be_nil
201
- end
105
+ it "should fetch the specified file when applied" do
106
+ job.size.should == 62664
107
+ end
202
108
 
203
- it "should not set the name url_attr if there isn't one, e.g. #{url}" do
204
- @job.fetch_url!(url)
205
- @job.url_attrs[:name].should be_nil
206
- end
207
- end
109
+ it "should set the url_attributes" do
110
+ job.url_attributes.name.should == 'egg.png'
208
111
  end
209
112
 
113
+ it "should set the name" do
114
+ job.name.should == 'egg.png'
115
+ end
210
116
  end
211
117
 
212
- describe "with content already there" do
213
-
118
+ describe "fetch_url" do
214
119
  before(:each) do
215
- @app = mock_app
216
- @job = Dragonfly::Job.new(@app, 'HELLO', :name => 'hello.txt', :a => :b)
217
- @temp_object = @job.temp_object
120
+ stub_request(:get, %r{http://place\.com/.*}).to_return(:body => 'result!')
218
121
  end
219
122
 
220
- describe "apply" do
221
- it "should return itself" do
222
- @job.apply.should == @job
223
- end
123
+ it "adds a step" do
124
+ job.fetch_url!('some.url')
125
+ job.steps.should match_steps([Dragonfly::Job::FetchUrl])
224
126
  end
225
127
 
226
- describe "process" do
227
- before(:each) do
228
- @job.url_attrs = {:some => 'thing'}
229
- @job.process!(:resize, '20x30')
230
- end
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
231
137
 
232
- it { @job.steps.should match_steps([Dragonfly::Job::Process]) }
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
233
143
 
234
- it "should use the processor when applied" do
235
- @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
236
- @job.data.should == 'hi'
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
237
154
  end
238
155
 
239
- it "should maintain the meta attributes" do
240
- @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return('hi')
241
- @job.meta.should == {:name => 'hello.txt', :a => :b}
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
242
159
  end
160
+ end
243
161
 
244
- it "should maintain the url_attrs" do
245
- @job.url_attrs.should == {:some => 'thing'}
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'
246
171
  end
247
172
 
248
- it "should allow returning an array with extra attributes from the processor" do
249
- @app.processor.should_receive(:process).with(@temp_object, :resize, '20x30').and_return(['hi', {:name => 'hello_20x30.txt', :eggs => 'asdf'}])
250
- @job.data.should == 'hi'
251
- @job.meta.should == {:name => 'hello_20x30.txt', :a => :b, :eggs => 'asdf'}
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'
252
176
  end
253
177
  end
254
178
 
255
- describe "encode" do
256
- before(:each) do
257
- @job.url_attrs = {:name => 'boid'}
258
- @job.encode!(:gif, 'bitrate' => 'mumma')
259
- end
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
260
188
 
261
- it { @job.steps.should match_steps([Dragonfly::Job::Encode]) }
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
262
198
 
263
- it "should use the encoder when applied" do
264
- @app.encoder.should_receive(:encode).with(@temp_object, :gif, 'bitrate' => 'mumma').and_return('alo')
265
- @job.data.should == 'alo'
266
- end
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
267
204
 
268
- it "should maintain the meta and update the format" do
269
- @app.encoder.should_receive(:encode).with(@temp_object, :gif, 'bitrate' => 'mumma').and_return('alo')
270
- @job.meta.should == {:name => 'hello.txt', :a => :b, :format => :gif}
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'
271
211
  end
272
212
 
273
- it "should update the format on the url_attrs" do
274
- @app.encoder.should_not_receive(:encode)
275
- @job.url_attrs[:format].should == :gif
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)
276
217
  end
218
+ end
219
+ end
277
220
 
278
- it "should allow returning an array with extra attributes form the encoder" do
279
- @app.encoder.should_receive(:encode).with(@temp_object, :gif, 'bitrate' => 'mumma').and_return(['alo', {:name => 'doobie', :eggs => 'fish'}])
280
- @job.data.should == 'alo'
281
- @job.meta.should == {:name => 'doobie', :a => :b, :eggs => 'fish', :format => :gif}
282
- end
221
+ describe "apply" do
222
+ it "should return itself" do
223
+ job.apply.should == job
224
+ end
225
+ end
283
226
 
284
- it "not allow overriding the format" do
285
- @app.encoder.should_receive(:encode).with(@temp_object, :gif, 'bitrate' => 'mumma').and_return(['alo', {:format => :png}])
286
- @job.apply.meta[:format].should == :gif
287
- end
227
+ describe "process" do
228
+ before :each do
229
+ app.add_processor(:resize){}
230
+ end
288
231
 
289
- it "should maintain the url_attrs" do
290
- @job.url_attrs[:name].should == 'boid'
291
- end
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
292
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')
293
246
  end
294
247
  end
295
248
 
296
249
  describe "analysis" do
250
+ let (:job) { Dragonfly::Job.new(app, "HELLO") }
251
+
297
252
  before(:each) do
298
- @app = test_app
299
- @job = @app.new_job('HELLO')
300
- @app.analyser.add(:num_letters){|temp_object, letter| temp_object.data.count(letter) }
253
+ app.add_analyser(:num_ls){|content| content.data.count('L') }
301
254
  end
302
255
  it "should return correctly when calling analyse" do
303
- @job.analyse(:num_letters, 'L').should == 2
304
- end
305
- it "should have mixed in the analyser method" do
306
- @job.num_letters('L').should == 2
307
- end
308
- it "should return nil from analyse if calling any old method" do
309
- @job.analyse(:robin_van_persie).should be_nil
310
- end
311
- it "should not allow calling any old method" do
312
- lambda{
313
- @job.robin_van_persie
314
- }.should raise_error(NoMethodError)
256
+ job.analyse(:num_ls).should == 2
315
257
  end
316
258
  it "should work correctly with chained jobs, applying before analysing" do
317
- @app.processor.add(:double){|temp_object| temp_object.data * 2 }
318
- @job.process(:double).num_letters('L').should == 4
259
+ app.add_processor(:double){|content| content.update(content.data * 2) }
260
+ job.process(:double).analyse(:num_ls).should == 4
319
261
  end
320
262
  end
321
263
 
322
264
  describe "defining extra steps after applying" do
323
265
  before(:each) do
324
- @app = mock_app
266
+ @app = test_app
267
+ @app.add_processor(:resize){}
268
+ @app.add_processor(:encode){}
325
269
  @job = Dragonfly::Job.new(@app)
326
- @job.temp_object = Dragonfly::TempObject.new("hello")
327
270
  @job.process! :resize
328
271
  @job.apply
329
- @job.encode! :micky
272
+ @job.process! :encode
330
273
  end
331
274
  it "should not call apply on already applied steps" do
332
275
  @job.steps[0].should_not_receive(:apply)
@@ -337,20 +280,13 @@ describe Dragonfly::Job do
337
280
  @job.apply
338
281
  end
339
282
  it "should return all steps" do
340
- @job.steps.should match_steps([
341
- Dragonfly::Job::Process,
342
- Dragonfly::Job::Encode
343
- ])
283
+ @job.steps.map{|step| step.name }.should == [:resize, :encode]
344
284
  end
345
285
  it "should return applied steps" do
346
- @job.applied_steps.should match_steps([
347
- Dragonfly::Job::Process
348
- ])
286
+ @job.applied_steps.map{|step| step.name }.should == [:resize]
349
287
  end
350
288
  it "should return the pending steps" do
351
- @job.pending_steps.should match_steps([
352
- Dragonfly::Job::Encode
353
- ])
289
+ @job.pending_steps.map{|step| step.name }.should == [:encode]
354
290
  end
355
291
  it "should not call apply on any steps when already applied" do
356
292
  @job.apply
@@ -363,8 +299,10 @@ describe Dragonfly::Job do
363
299
  describe "chaining" do
364
300
 
365
301
  before(:each) do
366
- @app = mock_app
302
+ @app = test_app
367
303
  @job = Dragonfly::Job.new(@app)
304
+ @app.add_processor(:resize){|content, length| content.update(content.data[0...length]) }
305
+ @app.store("SOME_DATA", {}, :uid => 'some_uid')
368
306
  end
369
307
 
370
308
  it "should return itself if bang is used" do
@@ -378,7 +316,7 @@ describe Dragonfly::Job do
378
316
  describe "when a chained job is defined" do
379
317
  before(:each) do
380
318
  @job.fetch!('some_uid')
381
- @job2 = @job.process(:resize, '30x30')
319
+ @job2 = @job.process(:resize, 4)
382
320
  end
383
321
 
384
322
  it "should return the correct steps for the original job" do
@@ -403,61 +341,42 @@ describe Dragonfly::Job do
403
341
  end
404
342
 
405
343
  it "should return the correct data for the new job" do
406
- @job2.data.should == 'SOME_PROCESSED_DATA'
407
- end
408
-
409
- it "should not affect the other one when one is applied" do
410
- @job.apply
411
- @job.applied_steps.should match_steps([
412
- Dragonfly::Job::Fetch
413
- ])
414
- @job.pending_steps.should match_steps([
415
- ])
416
- @job.temp_object.data.should == 'SOME_DATA'
417
- @job2.applied_steps.should match_steps([
418
- ])
419
- @job2.pending_steps.should match_steps([
420
- Dragonfly::Job::Fetch,
421
- Dragonfly::Job::Process
422
- ])
423
- @job2.temp_object.should be_nil
344
+ @job2.data.should == 'SOME'
424
345
  end
425
346
  end
426
347
 
427
348
  end
428
349
 
429
350
  describe "applied?" do
430
- before(:each) do
431
- @app = test_app
432
- end
433
351
  it "should return true when empty" do
434
- @app.new_job.should be_applied
352
+ app.new_job.should be_applied
435
353
  end
436
354
  it "should return false when not applied" do
437
- @app.fetch('eggs').should_not be_applied
355
+ app.fetch('eggs').should_not be_applied
438
356
  end
439
357
  it "should return true when applied" do
440
- @app.datastore.should_receive(:retrieve).with('eggs').and_return("cracked")
441
- job = @app.fetch('eggs').apply
358
+ job = app.fetch('eggs')
359
+ app.datastore.should_receive(:read).with('eggs').and_return ["", {}]
360
+ job.apply
442
361
  job.should be_applied
443
362
  end
444
363
  end
445
364
 
446
365
  describe "to_a" do
447
366
  before(:each) do
448
- @app = mock_app
367
+ @app = test_app
368
+ @app.add_generator(:plasma){}
369
+ @app.add_processor(:resize){}
449
370
  end
450
371
  it "should represent all the steps in array form" do
451
372
  job = Dragonfly::Job.new(@app)
452
373
  job.fetch! 'some_uid'
453
374
  job.generate! :plasma # you wouldn't really call this after fetch but still works
454
375
  job.process! :resize, '30x40'
455
- job.encode! :gif, 'bitrate' => 20
456
376
  job.to_a.should == [
457
377
  ['f', 'some_uid'],
458
378
  ['g', :plasma],
459
- ['p', :resize, '30x40'],
460
- ['e', :gif, {'bitrate' => 20}]
379
+ ['p', :resize, '30x40']
461
380
  ]
462
381
  end
463
382
  end
@@ -466,6 +385,8 @@ describe Dragonfly::Job do
466
385
 
467
386
  before(:each) do
468
387
  @app = test_app
388
+ @app.add_generator(:plasma){}
389
+ @app.add_processor(:resize){}
469
390
  end
470
391
 
471
392
  describe "a well-defined array" do
@@ -473,8 +394,7 @@ describe Dragonfly::Job do
473
394
  @job = Dragonfly::Job.from_a([
474
395
  ['f', 'some_uid'],
475
396
  ['g', 'plasma'],
476
- ['p', 'resize', '30x40'],
477
- ['e', 'gif', {'bitrate' => 20}]
397
+ ['p', 'resize', '30x40']
478
398
  ], @app)
479
399
  end
480
400
  it "should have the correct step types" do
@@ -482,14 +402,12 @@ describe Dragonfly::Job do
482
402
  Dragonfly::Job::Fetch,
483
403
  Dragonfly::Job::Generate,
484
404
  Dragonfly::Job::Process,
485
- Dragonfly::Job::Encode
486
405
  ])
487
406
  end
488
407
  it "should have the correct args" do
489
408
  @job.steps[0].args.should == ['some_uid']
490
409
  @job.steps[1].args.should == ['plasma']
491
410
  @job.steps[2].args.should == ['resize', '30x40']
492
- @job.steps[3].args.should == ['gif', {'bitrate' => 20}]
493
411
  end
494
412
  it "should have no applied steps" do
495
413
  @job.applied_steps.should be_empty
@@ -526,6 +444,7 @@ describe Dragonfly::Job do
526
444
  describe "serialization" do
527
445
  before(:each) do
528
446
  @app = test_app
447
+ @app.add_processor(:resize_and_crop){}
529
448
  @job = Dragonfly::Job.new(@app).fetch('uid').process(:resize_and_crop, 'width' => 270, 'height' => 92, 'gravity' => 'n')
530
449
  end
531
450
  it "should serialize itself" do
@@ -550,25 +469,28 @@ describe Dragonfly::Job do
550
469
  end
551
470
 
552
471
  context 'legacy urls are enabled' do
472
+ before do
473
+ @app.allow_legacy_urls = true
474
+ end
475
+
553
476
  it "works with marshal encoded strings (deprecated)" do
554
477
  job = Dragonfly::Job.deserialize("BAhbBlsHSSIGZgY6BkVUSSINc29tZV91aWQGOwBU", @app)
555
478
  job.fetch_step.uid.should == 'some_uid'
556
479
  end
557
480
 
558
481
  it "checks for potentially malicious strings" do
559
- string = Dragonfly::Serializer.marshal_encode(Dragonfly::TempObject.new('a'))
482
+ string = Dragonfly::Serializer.marshal_b64_encode(Dragonfly::TempObject.new('a'))
560
483
  expect{
561
484
  Dragonfly::Job.deserialize(string, @app)
562
485
  }.to raise_error(Dragonfly::Serializer::MaliciousString)
563
486
  end
564
487
  end
565
488
 
566
- context 'legacy urls are disabled' do
489
+ context 'legacy urls are disabled (default)' do
567
490
  it "rejects marshal encoded strings " do
568
- @app.allow_legacy_urls = false
569
491
  expect {Dragonfly::Job.deserialize("BAhbBlsHSSIGZgY6BkVUSSINc29tZV91aWQGOwBU", @app)}.to raise_error(Dragonfly::Serializer::BadString)
570
492
  end
571
- end
493
+ end
572
494
  end
573
495
 
574
496
  describe "to_app" do
@@ -583,122 +505,82 @@ describe Dragonfly::Job do
583
505
  end
584
506
  end
585
507
 
586
- describe "url" do
508
+ describe "update_url_attributes" do
587
509
  before(:each) do
588
510
  @app = test_app
589
- @job = Dragonfly::Job.new(@app)
511
+ @job = Dragonfly::Job.new(:app)
512
+ @job.url_attributes.hello = 'goose'
590
513
  end
591
-
592
- it "should return nil if there are no steps" do
593
- @job.url.should be_nil
514
+ it "updates the url_attributes" do
515
+ @job.update_url_attributes(:jimmy => 'cricket')
516
+ @job.url_attributes.hello.should == 'goose'
517
+ @job.url_attributes.jimmy.should == 'cricket'
594
518
  end
519
+ it "overrides keys" do
520
+ @job.update_url_attributes(:hello => 'cricket')
521
+ @job.url_attributes.hello.should == 'cricket'
522
+ end
523
+ end
595
524
 
596
- describe "using url_attrs in the url" do
597
- before(:each) do
598
- @app.server.url_format = '/media/:job/:zoo'
599
- @job.generate!(:fish)
600
- end
601
- it "should act as per usual if no params given" do
602
- @job.url.should == "/media/#{@job.serialize}"
603
- end
604
- it "should add given params" do
605
- @job.url(:zoo => 'jokes', :on => 'me').should == "/media/#{@job.serialize}/jokes?on=me"
606
- end
607
- it "should use the url_attr if it exists" do
608
- @job.url_attrs[:zoo] = 'hair'
609
- @job.url.should == "/media/#{@job.serialize}/hair"
610
- end
611
- it "should not add any url_attrs that aren't needed" do
612
- @job.url_attrs[:gump] = 'flub'
613
- @job.url.should == "/media/#{@job.serialize}"
614
- end
615
- it "should override if a param is passed in" do
616
- @job.url_attrs[:zoo] = 'hair'
617
- @job.url(:zoo => 'dare').should == "/media/#{@job.serialize}/dare"
618
- end
525
+ describe "url_attributes" do
526
+ it "doesn't interfere with other jobs' attributes" do
527
+ job.url_attributes.zoo = 'hair'
528
+ job2 = job.dup
529
+ job2.url_attributes.zoo = 'dare'
619
530
 
620
- describe "basename" do
621
- before(:each) do
622
- @app.server.url_format = '/:job/:basename'
623
- end
624
- it "should use the name" do
625
- @job.url_attrs = {:name => 'hello.egg'}
626
- @job.url.should == "/#{@job.serialize}/hello"
627
- end
628
- it "should not set if neither exist" do
629
- @job.url_attrs = {}
630
- @job.url.should == "/#{@job.serialize}"
631
- end
632
- end
531
+ job.url_attributes.zoo.should == 'hair'
532
+ job2.url_attributes.zoo.should == 'dare'
533
+ end
534
+ end
633
535
 
634
- describe "ext" do
635
- before(:each) do
636
- @app.server.url_format = '/:job.:ext'
637
- @job.url_attrs = {:name => 'hello.egg', :ext => 'hi'}
638
- end
639
- it "should use the name" do
640
- @job.url_attrs = {:name => 'hello.egg'}
641
- @job.url.should == "/#{@job.serialize}.egg"
642
- end
643
- it "should not set if neither exist" do
644
- @job.url_attrs = {}
645
- @job.url.should == "/#{@job.serialize}"
646
- end
647
- end
536
+ describe "url" do
537
+ let (:app) { test_app }
538
+ let (:job) { Dragonfly::Job.new(app) }
648
539
 
649
- describe "format" do
650
- before(:each) do
651
- @app.server.url_format = '/:job.:format'
652
- end
653
- it "should use the url_attr if it exists" do
654
- @job.url_attrs = {:ext => 'hi', :format => :txt}
655
- @job.url.should == "/#{@job.serialize}.txt"
656
- end
657
- it "should use the ext if format url_attr doesn't exist" do
658
- @job.url_attrs = {:name => 'hup.hi'}
659
- @job.url.should == "/#{@job.serialize}.hi"
660
- end
661
- it "should not use the ext if format meta doesn't exist and trust_file_extensions is switched off" do
662
- @job.url_attrs = {:name => 'hup.hi'}
663
- @app.trust_file_extensions = false
664
- @job.url.should == "/#{@job.serialize}"
665
- end
666
- it "should not set if neither exist" do
667
- @job.url_attrs = {}
668
- @job.url.should == "/#{@job.serialize}"
669
- end
670
- end
540
+ it "returns nil if there are no steps" do
541
+ job.url.should be_nil
542
+ end
543
+
544
+ it "uses the server url otherwise" do
545
+ job.fetch!("some_stuff")
546
+ opts = {:some => "opts"}
547
+ app.server.should_receive(:url_for).with(job, opts).and_return("some.url")
548
+ job.url(opts).should == "some.url"
671
549
  end
672
550
  end
673
551
 
674
552
  describe "to_fetched_job" do
675
- before(:each) do
676
- @app = test_app
677
- @job = @app.create("HELLO")
553
+ let (:fetched_job) { job.to_fetched_job('some_uid') }
554
+
555
+ before :each do
556
+ job.content.update "bugs", "bug" => "bear"
557
+ job.update_url_attributes "boog" => "bar"
678
558
  end
679
- it "should maintain the same temp_object and be already applied" do
680
- new_job = @job.to_fetched_job('some_uid')
681
- new_job.data.should == 'HELLO'
682
- new_job.to_a.should == [
559
+
560
+ it "updates the steps" do
561
+ fetched_job.to_a.should == [
683
562
  ['f', 'some_uid']
684
563
  ]
685
- new_job.pending_steps.should be_empty
564
+ fetched_job.should be_applied
686
565
  end
687
- it "should maintain the meta" do
688
- @job.meta = {:right => 'said fred'}
689
- new_job = @job.to_fetched_job('some_uid')
690
- new_job.meta.should == {:right => 'said fred'}
566
+ it "maintains the same content (but different object)" do
567
+ fetched_job.data.should == "bugs"
568
+ fetched_job.meta.should == {"bug" => "bear"}
569
+ job.content.update("dogs")
570
+ fetched_job.data.should == "bugs" # still
691
571
  end
692
- it "should maintain the url_attrs" do
693
- @job.url_attrs = {:dang => 'that dawg'}
694
- new_job = @job.to_fetched_job('some_uid')
695
- new_job.url_attrs.should == {:dang => 'that dawg'}
572
+ it "maintains the url_attributes (but different object)" do
573
+ fetched_job.url_attributes.boog.should == "bar"
574
+ job.update_url_attributes "boog" => "dogs"
575
+ fetched_job.url_attributes.boog.should == "bar" # still
696
576
  end
697
577
  end
698
578
 
699
579
  describe "to_unique_s" do
700
580
  it "should use the arrays of args to create the string" do
701
- job = test_app.fetch('uid').process(:gug, 4, 'some' => 'arg', 'and' => 'more')
581
+ app = test_app
582
+ app.add_processor(:gug){}
583
+ job = app.fetch('uid').process(:gug, 4, 'some' => 'arg', 'and' => 'more')
702
584
  job.to_unique_s.should == 'fuidpgug4andmoresomearg'
703
585
  end
704
586
  end
@@ -742,45 +624,18 @@ describe Dragonfly::Job do
742
624
  end
743
625
  end
744
626
 
745
- describe "setting the name" do
746
- before(:each) do
747
- @app = test_app
748
- @job = @app.new_job("HELLO", :name => 'not.me')
749
- end
750
- it "should allow setting the name" do
751
- @job.name = 'wassup.doc'
752
- @job.name.should == 'wassup.doc'
753
- end
754
- end
755
-
756
- describe "setting the meta" do
757
- before(:each) do
758
- @app = test_app
759
- @job = @app.new_job("HiThere", :five => 'beans')
760
- end
761
- it "should allow setting the meta" do
762
- @job.meta = {:doogie => 'ladders'}
763
- @job.meta.should == {:doogie => 'ladders'}
764
- end
765
- it "should allow updating the meta" do
766
- @job.meta[:doogie] = 'ladders'
767
- @job.meta.should == {:five => 'beans', :doogie => 'ladders'}
768
- end
769
- end
770
-
771
627
  describe "b64_data" do
772
- before(:each) do
773
- @app = test_app
774
- end
775
- it "should return a string using the data:URI schema" do
776
- job = @app.new_job("HELLO", :name => 'text.txt')
777
- job.b64_data.should == "data:text/plain;base64,SEVMTE8=\n"
628
+ it "takes it from the result" do
629
+ job.should_receive(:apply)
630
+ job.b64_data.should =~ /^data:/
778
631
  end
779
632
  end
780
633
 
781
634
  describe "querying stuff without applying steps" do
782
635
  before(:each) do
783
636
  @app = test_app
637
+ @app.add_generator(:ponies){}
638
+ @app.add_processor(:jam){}
784
639
  end
785
640
 
786
641
  describe "fetch_step" do
@@ -788,7 +643,7 @@ describe Dragonfly::Job do
788
643
  @app.generate(:ponies).process(:jam).fetch_step.should be_nil
789
644
  end
790
645
  it "should return the fetch step otherwise" do
791
- step = @app.fetch('hello').process(:cheese).fetch_step
646
+ step = @app.fetch('hello').process(:jam).fetch_step
792
647
  step.should be_a(Dragonfly::Job::Fetch)
793
648
  step.uid.should == 'hello'
794
649
  end
@@ -817,7 +672,7 @@ describe Dragonfly::Job do
817
672
  @app.generate(:ponies).process(:jam).fetch_file_step.should be_nil
818
673
  end
819
674
  it "should return the fetch_file step otherwise" do
820
- step = @app.fetch_file('/my/file.png').process(:cheese).fetch_file_step
675
+ step = @app.fetch_file('/my/file.png').process(:jam).fetch_file_step
821
676
  step.should be_a(Dragonfly::Job::FetchFile)
822
677
  if Dragonfly.running_on_windows?
823
678
  step.path.should =~ %r(:/my/file\.png$)
@@ -825,6 +680,10 @@ describe Dragonfly::Job do
825
680
  step.path.should == '/my/file.png'
826
681
  end
827
682
  end
683
+ it "converts pathname to a string in to_a" do
684
+ job = @app.fetch_file(Pathname.new('some/where'))
685
+ job.to_a.should == [['ff', 'some/where']]
686
+ end
828
687
  end
829
688
 
830
689
  describe "fetch_url_step" do
@@ -832,7 +691,7 @@ describe Dragonfly::Job do
832
691
  @app.generate(:ponies).fetch_url_step.should be_nil
833
692
  end
834
693
  it "should return the fetch_url step otherwise" do
835
- step = @app.fetch_url('egg.heads').process(:cheese).fetch_url_step
694
+ step = @app.fetch_url('egg.heads').process(:jam).fetch_url_step
836
695
  step.should be_a(Dragonfly::Job::FetchUrl)
837
696
  step.url.should == 'http://egg.heads'
838
697
  end
@@ -843,7 +702,7 @@ describe Dragonfly::Job do
843
702
  @app.fetch('many/ponies').process(:jam).generate_step.should be_nil
844
703
  end
845
704
  it "should return the generate step otherwise" do
846
- step = @app.generate(:ponies).process(:cheese).generate_step
705
+ step = @app.generate(:ponies).process(:jam).generate_step
847
706
  step.should be_a(Dragonfly::Job::Generate)
848
707
  step.name.should == :ponies
849
708
  end
@@ -851,7 +710,8 @@ describe Dragonfly::Job do
851
710
 
852
711
  describe "process_steps" do
853
712
  it "should return the processing steps" do
854
- job = @app.fetch('many/ponies').process(:jam).process(:eggs).encode(:gif)
713
+ @app.add_processor(:eggs){}
714
+ job = @app.fetch('many/ponies').process(:jam).process(:eggs)
855
715
  job.process_steps.should match_steps([
856
716
  Dragonfly::Job::Process,
857
717
  Dragonfly::Job::Process
@@ -859,232 +719,44 @@ describe Dragonfly::Job do
859
719
  end
860
720
  end
861
721
 
862
- describe "encode_step" do
863
- it "should return nil if it doesn't exist" do
864
- @app.generate(:ponies).encode_step.should be_nil
865
- end
866
- it "should return the last encode step otherwise" do
867
- step = @app.fetch('hello').encode(:smells).encode(:cheese).encode_step
868
- step.should be_a(Dragonfly::Job::Encode)
869
- step.format.should == :cheese
870
- end
871
- end
872
-
873
722
  describe "step_types" do
874
723
  it "should return the step types" do
875
- job = @app.fetch('eggs').process(:beat, 'strongly').encode(:meringue)
876
- job.step_types.should == [:fetch, :process, :encode]
724
+ job = @app.fetch('eggs').process(:jam)
725
+ job.step_types.should == [:fetch, :process]
877
726
  end
878
727
  end
879
728
  end
880
729
 
881
730
  describe "meta" do
882
- before(:each) do
883
- @app = test_app
884
- @app.generator.add(:gollum){|t| "OK"}
885
- @job = @app.new_job("Goo")
886
- end
887
- it "should default meta to an empty hash" do
888
- @job.meta.should == {}
889
- end
890
- it "should allow setting" do
891
- @job.meta = {:a => :b}
892
- @job.meta.should == {:a => :b}
893
- end
894
- it "should apply the job" do
895
- @job.should_receive :apply
896
- @job.meta
897
- end
898
- it "should apply the job before setting (for consistency)" do
899
- @job.should_receive :apply
900
- @job.meta = {}
901
- end
902
- it "should allow setting on initialize" do
903
- job = @app.new_job('asdf', :b => :c)
904
- job.meta.should == {:b => :c}
905
- end
906
- it "should keep them when chained" do
907
- @job.meta[:darn] = 'it'
908
- @job.generate(:gollum).meta.should == {:darn => 'it'}
731
+ it "delegates to the result" do
732
+ job.should_receive(:apply)
733
+ job.meta = {'a' => 'b'}
734
+ job.should_receive(:apply)
735
+ job.meta.should == {'a' => 'b'}
909
736
  end
910
737
  end
911
738
 
912
- describe "sanity check for name, basename, ext" do
913
- before(:each) do
914
- @app = test_app
915
- @job = @app.new_job('asdf')
916
- end
917
-
739
+ describe "sanity check for name, basename, ext, mime_type" do
918
740
  it "should default to nil" do
919
- @job.name.should be_nil
741
+ job.name.should be_nil
920
742
  end
921
743
 
922
744
  it "reflect the meta" do
923
- @job.meta[:name] = 'monkey.egg'
924
- @job.name.should == 'monkey.egg'
925
- @job.basename.should == 'monkey'
926
- @job.ext.should == 'egg'
927
- end
928
- end
929
-
930
- describe "format" do
931
- before(:each) do
932
- @app = test_app
933
- end
934
- it "should default to nil" do
935
- job = @app.new_job("HELLO")
936
- job.format.should be_nil
937
- end
938
- it "should use the meta format if it exists" do
939
- job = @app.new_job("HELLO")
940
- job.meta[:format] = :txt
941
- job.format.should == :txt
942
- end
943
- it "should use the analyser format if it exists" do
944
- @app.analyser.add :format do |temp_object|
945
- :egg
946
- end
947
- job = @app.new_job("HELLO")
948
- job.format.should == :egg
949
- end
950
- it "should use the file extension if it has no format" do
951
- job = @app.new_job("HIMATE", :name => 'test.pdf')
952
- job.format.should == :pdf
953
- end
954
- it "should not use the file extension if it's been switched off" do
955
- @app.trust_file_extensions = false
956
- job = @app.new_job("HIMATE", :name => 'test.pdf')
957
- job.format.should be_nil
958
- end
959
- it "should prefer the set format over the file extension" do
960
- job = @app.new_job("HELLO", :name => 'test.pdf', :format => :txt)
961
- job.format.should == :txt
962
- end
963
- it "should prefer the file extension over the analysed format" do
964
- @app.analyser.add :format do |temp_object|
965
- :egg
966
- end
967
- job = @app.new_job("HELLO", :name => 'test.pdf')
968
- job.format.should == :pdf
969
- end
970
- it "should apply the job" do
971
- @app.generator.add(:test){ ["skid marks", {:name => 'terry.burton'}] }
972
- job = @app.generate(:test)
973
- job.format.should == :burton
974
- job.should be_applied
975
- end
976
- end
977
-
978
- describe "mime_type" do
979
- before(:each) do
980
- @app = test_app
981
- end
982
- it "should return the correct mime_type if the format is given" do
983
- @job = @app.new_job("HIMATE")
984
- @job.should_receive(:format).and_return(:tiff)
985
- @job.mime_type.should == 'image/tiff'
986
- end
987
- it "should fall back to the mime_type analyser if the format is nil" do
988
- @app.analyser.add :mime_type do |temp_object|
989
- 'image/jpeg'
990
- end
991
- @job = @app.new_job("HIMATE")
992
- @job.mime_type.should == 'image/jpeg'
993
- end
994
- it "should fall back to the fallback mime_type if neither format or analyser exist" do
995
- @app.new_job("HIMATE").mime_type.should == 'application/octet-stream'
745
+ job.meta['name'] = 'monkey.png'
746
+ job.name.should == 'monkey.png'
747
+ job.basename.should == 'monkey'
748
+ job.ext.should == 'png'
749
+ job.mime_type.should == 'image/png'
996
750
  end
997
751
  end
998
752
 
999
753
  describe "store" do
1000
- before(:each) do
1001
- @app = test_app
1002
- @app.generator.add(:test){ ["Toes", {:name => 'doogie.txt'}] }
1003
- @job = @app.generate(:test)
1004
- end
1005
- it "should store its data along with the meta and mime_type" do
1006
- @job.meta[:eggs] = 'doolally'
1007
- @app.datastore.should_receive(:store).with do |temp_object, opts|
1008
- temp_object.data.should == "Toes"
1009
- temp_object.name.should == 'doogie.txt'
1010
- temp_object.meta[:eggs].should == 'doolally'
1011
- opts[:mime_type].should == 'text/plain'
1012
- end
1013
- @job.store
1014
- end
1015
- it "should add extra opts" do
1016
- @app.datastore.should_receive(:store).with(anything, hash_including(:path => 'blah', :mime_type => 'text/plain'))
1017
- @job.store(:path => 'blah')
1018
- end
1019
- it "should pass in its meta, for deprecated datastores" do
1020
- @job.meta[:beans] = 5
1021
- @app.datastore.should_receive(:store).with do |temp_object, opts|
1022
- opts[:meta].should == {:beans => 5, :name => 'doogie.txt'}
1023
- end
1024
- @job.store
1025
- end
1026
- end
1027
-
1028
- describe "dealing with original_filename" do
1029
- before(:each) do
1030
- @string = "terry"
1031
- @string.stub!(:original_filename).and_return("gum.tree")
1032
- @app = test_app
1033
- @app.generator.add(:test){ @string }
1034
- end
1035
- it "should set it as the name" do
1036
- @app.create(@string).name.should == 'gum.tree'
1037
- end
1038
- it "should prefer the initialized name over the original_filename" do
1039
- @app.create(@string, :name => 'doo.berry').name.should == 'doo.berry'
1040
- end
1041
- it "should work with e.g. generators" do
1042
- @app.generate(:test).apply.name.should == 'gum.tree'
1043
- end
1044
- it "should favour an e.g. generator returned name" do
1045
- @app.generator.add(:test2){ [@string, {:name => 'gen.ome'}] }
1046
- @app.generate(:test2).apply.name.should == 'gen.ome'
1047
- end
1048
- it "should not overwrite a set name" do
1049
- job = @app.generate(:test)
1050
- job.name = 'egg.mumma'
1051
- job.apply.name.should == 'egg.mumma'
1052
- end
1053
- end
1054
-
1055
- describe "deprecated meta format" do
1056
- before(:each) do
1057
- @app = test_app
1058
- end
1059
- it "should still work if the datastore/whatever returns meta nested in :meta key" do
1060
- @app.datastore.should_receive(:retrieve).with('some_uid').and_return(['HELLO', {:name => 'test.txt', :meta => {:some => 'meta'}}])
1061
- job = @app.fetch('some_uid').apply
1062
- job.meta.should == {:name => 'test.txt', :some => 'meta'}
1063
- end
1064
- end
1065
-
1066
- describe "close" do
1067
- before(:each) do
1068
- @app = test_app
1069
- @app.generator.add(:toast){ "toast" }
1070
- @app.processor.add(:upcase){|t| t.data.upcase }
1071
- @job = @app.generate(:toast)
1072
- @path1 = @job.tempfile.path
1073
- @job.process!(:upcase)
1074
- @path2 = @job.tempfile.path
1075
- end
1076
-
1077
- it "should clean up tempfiles for the last temp_object" do
1078
- File.exist?(@path2).should be_true
1079
- @job.close
1080
- File.exist?(@path2).should be_false
1081
- end
1082
-
1083
- it "should clean up tempfiles for previous temp_objects" do
1084
- File.exist?(@path1).should be_true
1085
- @job.close
1086
- File.exist?(@path1).should be_false
754
+ it "calls store on the applied content" do
755
+ job.should_receive(:apply)
756
+ app.datastore.should_receive(:write).with(job.content, {})
757
+ job.store
1087
758
  end
1088
759
  end
1089
760
 
1090
761
  end
762
+