dragonfly 0.9.15 → 1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dragonfly might be problematic. Click here for more details.

Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -8
  3. data/.travis.yml +11 -0
  4. data/Gemfile +1 -0
  5. data/History.md +52 -2
  6. data/LICENSE +1 -1
  7. data/README.md +38 -95
  8. data/dev/grid.jpg +0 -0
  9. data/dev/irbrc.rb +27 -0
  10. data/dev/rails_template.rb +38 -0
  11. data/dev/test.ru +56 -0
  12. data/dev/test_rails +19 -0
  13. data/dragonfly.gemspec +3 -21
  14. data/lib/dragonfly.rb +45 -44
  15. data/lib/dragonfly/app.rb +175 -96
  16. data/lib/dragonfly/configurable.rb +71 -170
  17. data/lib/dragonfly/content.rb +211 -0
  18. data/lib/dragonfly/core_ext/object.rb +1 -6
  19. data/lib/dragonfly/file_data_store.rb +197 -0
  20. data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
  21. data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
  22. data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
  23. data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
  24. data/lib/dragonfly/image_magick/generators/text.rb +127 -0
  25. data/lib/dragonfly/image_magick/plugin.rb +83 -0
  26. data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
  27. data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
  28. data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
  29. data/lib/dragonfly/job.rb +118 -134
  30. data/lib/dragonfly/job_endpoint.rb +2 -0
  31. data/lib/dragonfly/memory_data_store.rb +34 -0
  32. data/lib/dragonfly/middleware.rb +5 -3
  33. data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
  34. data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
  35. data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
  36. data/lib/dragonfly/model/class_methods.rb +109 -0
  37. data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
  38. data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
  39. data/lib/dragonfly/railtie.rb +8 -6
  40. data/lib/dragonfly/register.rb +27 -0
  41. data/lib/dragonfly/response.rb +47 -52
  42. data/lib/dragonfly/routed_endpoint.rb +4 -0
  43. data/lib/dragonfly/serializer.rb +15 -5
  44. data/lib/dragonfly/server.rb +56 -29
  45. data/lib/dragonfly/shell.rb +12 -23
  46. data/lib/dragonfly/spec/data_store_examples.rb +64 -0
  47. data/lib/dragonfly/temp_object.rb +32 -47
  48. data/lib/dragonfly/url_attributes.rb +19 -22
  49. data/lib/dragonfly/url_mapper.rb +3 -0
  50. data/lib/dragonfly/utils.rb +12 -0
  51. data/lib/dragonfly/version.rb +1 -1
  52. data/lib/dragonfly/whitelist.rb +19 -0
  53. data/lib/rails/generators/dragonfly/USAGE +8 -0
  54. data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
  55. data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
  56. data/samples/gif.gif +0 -0
  57. data/spec/dragonfly/app_spec.rb +270 -64
  58. data/spec/dragonfly/configurable_spec.rb +142 -418
  59. data/spec/dragonfly/content_spec.rb +353 -0
  60. data/spec/dragonfly/cookie_monster_spec.rb +2 -1
  61. data/spec/dragonfly/file_data_store_spec.rb +301 -0
  62. data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
  63. data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
  64. data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
  65. data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
  66. data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
  67. data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
  68. data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
  69. data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
  70. data/spec/dragonfly/job_endpoint_spec.rb +30 -73
  71. data/spec/dragonfly/job_spec.rb +280 -608
  72. data/spec/dragonfly/memory_data_store_spec.rb +20 -0
  73. data/spec/dragonfly/middleware_spec.rb +47 -27
  74. data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
  75. data/spec/dragonfly/model/validations_spec.rb +196 -0
  76. data/spec/dragonfly/register_spec.rb +35 -0
  77. data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
  78. data/spec/dragonfly/serializer_spec.rb +13 -15
  79. data/spec/dragonfly/server_spec.rb +122 -46
  80. data/spec/dragonfly/shell_spec.rb +43 -24
  81. data/spec/dragonfly/temp_object_spec.rb +69 -94
  82. data/spec/dragonfly/url_attributes_spec.rb +49 -0
  83. data/spec/dragonfly/utils_spec.rb +32 -0
  84. data/spec/dragonfly/whitelist_spec.rb +30 -0
  85. data/spec/dragonfly_spec.rb +43 -0
  86. data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
  87. data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
  88. data/spec/functional/configuration_spec.rb +19 -0
  89. data/spec/functional/model_urls_spec.rb +43 -41
  90. data/spec/functional/remote_on_the_fly_spec.rb +14 -16
  91. data/spec/functional/shell_commands_spec.rb +24 -14
  92. data/spec/functional/to_response_spec.rb +10 -10
  93. data/spec/functional/urls_spec.rb +5 -3
  94. data/spec/spec_helper.rb +23 -28
  95. data/spec/support/argument_matchers.rb +7 -8
  96. data/spec/support/image_matchers.rb +14 -36
  97. data/spec/support/model_helpers.rb +97 -0
  98. data/spec/support/simple_matchers.rb +12 -0
  99. metadata +92 -393
  100. data/.yardopts +0 -29
  101. data/Rakefile +0 -36
  102. data/config.ru +0 -14
  103. data/docs.watchr +0 -1
  104. data/extra_docs/Analysers.md +0 -68
  105. data/extra_docs/Caching.md +0 -23
  106. data/extra_docs/Configuration.md +0 -149
  107. data/extra_docs/Couch.md +0 -49
  108. data/extra_docs/DataStorage.md +0 -226
  109. data/extra_docs/Encoding.md +0 -67
  110. data/extra_docs/ExampleUseCases.md +0 -116
  111. data/extra_docs/GeneralUsage.md +0 -105
  112. data/extra_docs/Generators.md +0 -68
  113. data/extra_docs/Heroku.md +0 -50
  114. data/extra_docs/ImageMagick.md +0 -136
  115. data/extra_docs/Index.md +0 -33
  116. data/extra_docs/MimeTypes.md +0 -40
  117. data/extra_docs/Models.md +0 -441
  118. data/extra_docs/Mongo.md +0 -42
  119. data/extra_docs/Processing.md +0 -77
  120. data/extra_docs/Rack.md +0 -52
  121. data/extra_docs/Rails2.md +0 -57
  122. data/extra_docs/Rails3.md +0 -56
  123. data/extra_docs/ServingRemotely.md +0 -104
  124. data/extra_docs/Sinatra.md +0 -25
  125. data/extra_docs/URLs.md +0 -203
  126. data/features/images.feature +0 -47
  127. data/features/no_processing.feature +0 -14
  128. data/features/rails.feature +0 -8
  129. data/features/steps/common_steps.rb +0 -8
  130. data/features/steps/dragonfly_steps.rb +0 -66
  131. data/features/steps/rails_steps.rb +0 -40
  132. data/features/support/env.rb +0 -13
  133. data/features/support/setup.rb +0 -41
  134. data/fixtures/rails/files/app/models/album.rb +0 -6
  135. data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
  136. data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
  137. data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
  138. data/fixtures/rails/files/features/manage_album_images.feature +0 -38
  139. data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
  140. data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
  141. data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
  142. data/fixtures/rails/files/features/support/paths.rb +0 -17
  143. data/fixtures/rails/files/features/text_images.feature +0 -7
  144. data/fixtures/rails/template.rb +0 -20
  145. data/irbrc.rb +0 -19
  146. data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
  147. data/lib/dragonfly/analyser.rb +0 -58
  148. data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
  149. data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
  150. data/lib/dragonfly/config/heroku.rb +0 -26
  151. data/lib/dragonfly/config/image_magick.rb +0 -6
  152. data/lib/dragonfly/config/rails.rb +0 -20
  153. data/lib/dragonfly/data_storage.rb +0 -11
  154. data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
  155. data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
  156. data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
  157. data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
  158. data/lib/dragonfly/encoder.rb +0 -13
  159. data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
  160. data/lib/dragonfly/function_manager.rb +0 -67
  161. data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
  162. data/lib/dragonfly/generator.rb +0 -9
  163. data/lib/dragonfly/image_magick/analyser.rb +0 -53
  164. data/lib/dragonfly/image_magick/config.rb +0 -44
  165. data/lib/dragonfly/image_magick/encoder.rb +0 -57
  166. data/lib/dragonfly/image_magick/generator.rb +0 -147
  167. data/lib/dragonfly/image_magick/processor.rb +0 -114
  168. data/lib/dragonfly/image_magick/utils.rb +0 -46
  169. data/lib/dragonfly/image_magick_utils.rb +0 -4
  170. data/lib/dragonfly/job_builder.rb +0 -39
  171. data/lib/dragonfly/job_definitions.rb +0 -30
  172. data/lib/dragonfly/loggable.rb +0 -28
  173. data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
  174. data/lib/dragonfly/processor.rb +0 -9
  175. data/lib/dragonfly/rails/images.rb +0 -32
  176. data/lib/dragonfly/simple_cache.rb +0 -23
  177. data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
  178. data/spec/dragonfly/analyser_spec.rb +0 -123
  179. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
  180. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
  181. data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
  182. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
  183. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
  184. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
  185. data/spec/dragonfly/function_manager_spec.rb +0 -154
  186. data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
  187. data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
  188. data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
  189. data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
  190. data/spec/dragonfly/job_builder_spec.rb +0 -37
  191. data/spec/dragonfly/job_definitions_spec.rb +0 -57
  192. data/spec/dragonfly/loggable_spec.rb +0 -80
  193. data/spec/dragonfly/simple_cache_spec.rb +0 -27
  194. data/spec/dragonfly/url_attributes.rb +0 -47
  195. data/spec/functional/deprecations_spec.rb +0 -51
  196. data/spec/functional/image_magick_app_spec.rb +0 -27
  197. data/spec/test_imagemagick.ru +0 -49
  198. data/yard/handlers/configurable_attr_handler.rb +0 -38
  199. data/yard/setup.rb +0 -15
  200. data/yard/templates/default/fulldoc/html/css/common.css +0 -109
  201. data/yard/templates/default/layout/html/layout.erb +0 -93
  202. data/yard/templates/default/module/html/configuration_summary.erb +0 -31
  203. data/yard/templates/default/module/setup.rb +0 -17
@@ -0,0 +1,29 @@
1
+ module Dragonfly
2
+ module ImageMagick
3
+ module Processors
4
+ class Convert
5
+
6
+ def call(content, args='', opts={})
7
+ convert_command = content.env[:convert_command] || 'convert'
8
+ format = opts['format']
9
+
10
+ frame_string = "[#{opts['frame']}]" if opts['frame']
11
+ content.shell_update :ext => format do |old_path, new_path|
12
+ "#{convert_command} #{old_path}#{frame_string} #{args} #{new_path}"
13
+ end
14
+
15
+ if format
16
+ content.meta['format'] = format.to_s
17
+ content.ext = format
18
+ end
19
+ end
20
+
21
+ def update_url(attrs, args='', opts={})
22
+ format = opts['format']
23
+ attrs.ext = format if format
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ module Dragonfly
2
+ module ImageMagick
3
+ module Processors
4
+ class Encode
5
+
6
+ def update_url(attrs, format, args="")
7
+ attrs.ext = format.to_s
8
+ end
9
+
10
+ def call(content, format, args="")
11
+ content.process!(:convert, args, 'format' => format)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,76 @@
1
+ module Dragonfly
2
+ module ImageMagick
3
+ module Processors
4
+ class Thumb
5
+
6
+ GRAVITIES = {
7
+ 'nw' => 'NorthWest',
8
+ 'n' => 'North',
9
+ 'ne' => 'NorthEast',
10
+ 'w' => 'West',
11
+ 'c' => 'Center',
12
+ 'e' => 'East',
13
+ 'sw' => 'SouthWest',
14
+ 's' => 'South',
15
+ 'se' => 'SouthEast'
16
+ }
17
+
18
+ # Geometry string patterns
19
+ RESIZE_GEOMETRY = /^\d*x\d*[><%^!]?$|^\d+@$/ # e.g. '300x200!'
20
+ CROPPED_RESIZE_GEOMETRY = /^(\d+)x(\d+)#(\w{1,2})?$/ # e.g. '20x50#ne'
21
+ CROP_GEOMETRY = /^(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?$/ # e.g. '30x30+10+10'
22
+
23
+ def update_url(url_attributes, geometry, opts={})
24
+ format = opts['format']
25
+ url_attributes.ext = format if format
26
+ end
27
+
28
+ def call(content, geometry, opts={})
29
+ args = case geometry
30
+ when RESIZE_GEOMETRY
31
+ resize_args(geometry)
32
+ when CROPPED_RESIZE_GEOMETRY
33
+ resize_and_crop_args($1, $2, $3)
34
+ when CROP_GEOMETRY
35
+ crop_args(
36
+ 'width' => $1,
37
+ 'height' => $2,
38
+ 'x' => $3,
39
+ 'y' => $4,
40
+ 'gravity' => $5
41
+ )
42
+ else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
43
+ end
44
+ content.process!(:convert, args, opts)
45
+ end
46
+
47
+ private
48
+
49
+ def resize_args(geometry)
50
+ "-resize #{geometry}"
51
+ end
52
+
53
+ def crop_args(opts)
54
+ raise ArgumentError, "you can't give a crop offset and gravity at the same time" if opts['x'] && opts['gravity']
55
+
56
+ width = opts['width']
57
+ height = opts['height']
58
+ gravity = GRAVITIES[opts['gravity']]
59
+ x = "#{opts['x'] || 0}"
60
+ x = '+' + x unless x[/^[+-]/]
61
+ y = "#{opts['y'] || 0}"
62
+ y = '+' + y unless y[/^[+-]/]
63
+
64
+ "#{"-gravity #{gravity} " if gravity}-crop #{width}x#{height}#{x}#{y} +repage"
65
+ end
66
+
67
+ def resize_and_crop_args(width, height, gravity)
68
+ gravity = GRAVITIES[gravity || 'c']
69
+ "-resize #{width}x#{height}^^ -gravity #{gravity} -crop #{width}x#{height}+0+0 +repage"
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
76
+
@@ -1,8 +1,13 @@
1
1
  require 'forwardable'
2
2
  require 'digest/sha1'
3
- require 'base64'
3
+ require 'uri'
4
4
  require 'open-uri'
5
5
  require 'pathname'
6
+ require 'base64'
7
+ require 'dragonfly/serializer'
8
+ require 'dragonfly/content'
9
+ require 'dragonfly/url_attributes'
10
+ require 'dragonfly/job_endpoint'
6
11
 
7
12
  module Dragonfly
8
13
  class Job
@@ -10,9 +15,7 @@ module Dragonfly
10
15
  # Exceptions
11
16
  class AppDoesNotMatch < StandardError; end
12
17
  class JobAlreadyApplied < StandardError; end
13
- class NoContent < StandardError; end
14
18
  class NothingToProcess < StandardError; end
15
- class NothingToEncode < StandardError; end
16
19
  class InvalidArray < StandardError; end
17
20
  class NoSHAGiven < StandardError; end
18
21
  class IncorrectSHA < StandardError; end
@@ -20,9 +23,9 @@ module Dragonfly
20
23
  extend Forwardable
21
24
  def_delegators :result,
22
25
  :data, :file, :tempfile, :path, :to_file, :size, :each,
23
- :meta, :meta=, :name, :name=, :basename, :basename=, :ext, :ext=
24
- def_delegator :app,
25
- :server
26
+ :meta, :meta=, :add_meta, :name, :name=, :basename, :basename=, :ext, :ext=, :mime_type,
27
+ :analyse, :shell_eval, :store,
28
+ :b64_data
26
29
 
27
30
  class Step
28
31
 
@@ -51,6 +54,14 @@ module Dragonfly
51
54
 
52
55
  attr_reader :job, :args
53
56
 
57
+ def app
58
+ job.app
59
+ end
60
+
61
+ def to_a
62
+ [self.class.abbreviation, *args]
63
+ end
64
+
54
65
  def inspect
55
66
  "#{self.class.step_name}(#{args.map{|a| a.inspect }.join(', ')})"
56
67
  end
@@ -58,90 +69,135 @@ module Dragonfly
58
69
  end
59
70
 
60
71
  class Fetch < Step
72
+ class NotFound < RuntimeError; end
73
+
61
74
  def uid
62
75
  args.first
63
76
  end
77
+
64
78
  def apply
65
- content, meta = job.app.datastore.retrieve(uid)
66
- job.update(content, meta)
79
+ content, meta = app.datastore.read(uid)
80
+ raise NotFound, "uid #{uid} not found" if content.nil?
81
+ job.content.update(content, meta)
67
82
  end
68
83
  end
69
84
 
70
85
  class Process < Step
86
+ def init
87
+ processor.update_url(job.url_attributes, *arguments) if processor.respond_to?(:update_url)
88
+ end
89
+
71
90
  def name
72
91
  args.first.to_sym
73
92
  end
93
+
74
94
  def arguments
75
95
  args[1..-1]
76
96
  end
77
- def apply
78
- raise NothingToProcess, "Can't process because temp object has not been initialized. Need to fetch first?" unless job.temp_object
79
- content, meta = job.app.processor.process(job.temp_object, name, *arguments)
80
- job.update(content, meta)
81
- end
82
- end
83
97
 
84
- class Encode < Step
85
- def init
86
- job.url_attrs[:format] = format
87
- end
88
- def format
89
- args.first.to_sym
90
- end
91
- def arguments
92
- args[1..-1]
98
+ def processor
99
+ @processor ||= app.get_processor(name)
93
100
  end
101
+
94
102
  def apply
95
- raise NothingToEncode, "Can't encode because temp object has not been initialized. Need to fetch first?" unless job.temp_object
96
- content, meta = job.app.encoder.encode(job.temp_object, format, *arguments)
97
- job.update(content, (meta || {}).merge(:format => format))
103
+ processor.call(job.content, *arguments)
98
104
  end
99
105
  end
100
106
 
101
107
  class Generate < Step
108
+ def init
109
+ generator.update_url(job.url_attributes, *arguments) if generator.respond_to?(:update_url)
110
+ end
111
+
102
112
  def name
103
- args.first.to_sym
113
+ args.first
104
114
  end
115
+
116
+ def generator
117
+ @generator ||= app.get_generator(name)
118
+ end
119
+
105
120
  def arguments
106
121
  args[1..-1]
107
122
  end
123
+
108
124
  def apply
109
- content, meta = job.app.generator.generate(name, *arguments)
110
- job.update(content, meta)
125
+ generator.call(job.content, *arguments)
111
126
  end
112
127
  end
113
128
 
114
129
  class FetchFile < Step
130
+ def initialize(job, path)
131
+ super(job, path.to_s)
132
+ end
115
133
  def init
116
- job.url_attrs[:name] = filename
134
+ job.url_attributes.name = filename
117
135
  end
136
+
118
137
  def path
119
138
  @path ||= File.expand_path(args.first)
120
139
  end
140
+
121
141
  def filename
122
142
  @filename ||= File.basename(path)
123
143
  end
144
+
124
145
  def apply
125
- job.update(Pathname.new(path), :name => filename)
146
+ job.content.update(Pathname.new(path), 'name' => filename)
126
147
  end
127
148
  end
128
149
 
129
150
  class FetchUrl < Step
151
+ class ErrorResponse < RuntimeError
152
+ def initialize(status, body)
153
+ @status, @body = status, body
154
+ end
155
+ attr_reader :status, :body
156
+ end
157
+ class CannotHandle < RuntimeError; end
158
+
130
159
  def init
131
- job.url_attrs[:name] = filename
160
+ job.url_attributes.name = filename
132
161
  end
133
- def url
134
- @url ||= (args.first[%r<^\w+://>] ? args.first : "http://#{args.first}")
162
+
163
+ def uri
164
+ args.first
135
165
  end
136
- def path
137
- @path ||= URI.parse(url).path
166
+
167
+ def url
168
+ @url ||= uri =~ /^\w+:/ ? uri : "http://#{uri}"
138
169
  end
170
+
139
171
  def filename
140
- @filename ||= File.basename(path) if path[/[^\/]$/]
172
+ return if data_uri?
173
+ @filename ||= URI.parse(url).path[/[^\/]+$/]
141
174
  end
175
+
176
+ def data_uri?
177
+ uri =~ /^data:/
178
+ end
179
+
142
180
  def apply
143
- open(url) do |f|
144
- job.update(f.read, :name => filename)
181
+ if data_uri?
182
+ update_from_data_uri
183
+ else
184
+ open(URI.escape(url)) do |f|
185
+ job.content.update(f.read, 'name' => filename)
186
+ end
187
+ end
188
+ rescue OpenURI::HTTPError => e
189
+ status, message = e.io.status
190
+ raise ErrorResponse.new(status.to_i, e.io.read)
191
+ end
192
+
193
+ def update_from_data_uri
194
+ mime_type, b64_data = uri.scan(/^data:([^;]+);base64,(.*)$/)[0]
195
+ if mime_type && b64_data
196
+ data = Base64.decode64(b64_data)
197
+ ext = app.ext_for(mime_type)
198
+ job.content.update(data, 'name' => "file.#{ext}")
199
+ else
200
+ raise CannotHandle, "fetch_url can only deal with base64-encoded data uris with specified content type"
145
201
  end
146
202
  end
147
203
  end
@@ -149,7 +205,6 @@ module Dragonfly
149
205
  STEPS = [
150
206
  Fetch,
151
207
  Process,
152
- Encode,
153
208
  Generate,
154
209
  FetchFile,
155
210
  FetchUrl
@@ -173,10 +228,10 @@ module Dragonfly
173
228
 
174
229
  def deserialize(string, app)
175
230
  array = begin
176
- Serializer.json_decode(string)
231
+ Serializer.json_b64_decode(string)
177
232
  rescue Serializer::BadString
178
233
  if app.allow_legacy_urls
179
- Serializer.marshal_decode(string, :check_malicious => true) # legacy strings
234
+ Serializer.marshal_b64_decode(string, :check_malicious => true) # legacy strings
180
235
  else
181
236
  raise
182
237
  end
@@ -194,53 +249,24 @@ module Dragonfly
194
249
 
195
250
  end
196
251
 
197
- ####### Instance methods #######
198
-
199
- # This is needed because we need a way of overriding
200
- # the methods added to Job objects by the analyser and by
201
- # the job shortcuts like 'thumb', etc.
202
- # If we had traits/classboxes in ruby maybe this wouldn't be needed
203
- # Think of it as like a normal instance method but with a css-like !important after it
204
- module OverrideInstanceMethods
205
-
206
- def format
207
- apply
208
- meta[:format] || (ext.to_sym if ext && app.trust_file_extensions) || analyse(:format)
209
- end
210
-
211
- def mime_type
212
- app.mime_type_for(format) || analyse(:mime_type) || app.fallback_mime_type
213
- end
214
-
215
- def to_s
216
- super.sub(/#<Class:\w+>/, 'Extended Dragonfly::Job')
217
- end
218
-
219
- end
220
-
221
- def initialize(app, content=nil, meta={}, url_attrs={})
252
+ def initialize(app, content="", meta={})
222
253
  @app = app
223
- @steps = []
224
254
  @next_step_index = 0
225
- @previous_temp_objects = []
226
- update(content, meta) if content
227
- self.url_attrs = url_attrs
255
+ @steps = []
256
+ @content = Content.new(app, content, meta)
257
+ @url_attributes = UrlAttributes.new
228
258
  end
229
259
 
230
260
  # Used by 'dup' and 'clone'
231
261
  def initialize_copy(other)
232
- self.steps = other.steps.map do |step|
262
+ @steps = other.steps.map do |step|
233
263
  step.class.new(self, *step.args)
234
264
  end
265
+ @content = other.content.dup
266
+ @url_attributes = other.url_attributes.dup
235
267
  end
236
268
 
237
- attr_reader :app, :steps
238
- attr_reader :temp_object
239
-
240
- def temp_object=(temp_object)
241
- previous_temp_objects.push(@temp_object) if @temp_object
242
- @temp_object = temp_object
243
- end
269
+ attr_reader :app, :steps, :content
244
270
 
245
271
  # define fetch(), fetch!(), process(), etc.
246
272
  STEPS.each do |step_class|
@@ -258,10 +284,6 @@ module Dragonfly
258
284
  )
259
285
  end
260
286
 
261
- def analyse(method, *args)
262
- analyser.analyse(result, method, *args)
263
- end
264
-
265
287
  # Applying, etc.
266
288
 
267
289
  def apply
@@ -283,9 +305,7 @@ module Dragonfly
283
305
  end
284
306
 
285
307
  def to_a
286
- steps.map{|step|
287
- [step.class.abbreviation, *step.args]
288
- }
308
+ steps.map{|step| step.to_a }
289
309
  end
290
310
 
291
311
  # Serializing, etc.
@@ -295,10 +315,10 @@ module Dragonfly
295
315
  end
296
316
 
297
317
  def serialize
298
- Serializer.json_encode(to_a)
318
+ Serializer.json_b64_encode(to_a)
299
319
  end
300
320
 
301
- def unique_signature
321
+ def signature
302
322
  Digest::SHA1.hexdigest(to_unique_s)
303
323
  end
304
324
 
@@ -320,17 +340,15 @@ module Dragonfly
320
340
  # URLs, etc.
321
341
 
322
342
  def url(opts={})
323
- app.url_for(self, attributes_for_url.merge(opts)) unless steps.empty?
324
- end
325
-
326
- def url_attrs=(hash)
327
- @url_attrs = UrlAttributes[hash]
343
+ app.url_for(self, opts) unless steps.empty?
328
344
  end
329
345
 
330
- attr_reader :url_attrs
346
+ attr_reader :url_attributes
331
347
 
332
- def b64_data
333
- "data:#{mime_type};base64,#{Base64.encode64(data)}"
348
+ def update_url_attributes(hash)
349
+ hash.each do |key, value|
350
+ url_attributes.send("#{key}=", value)
351
+ end
334
352
  end
335
353
 
336
354
  # to_stuff...
@@ -344,7 +362,8 @@ module Dragonfly
344
362
  end
345
363
 
346
364
  def to_fetched_job(uid)
347
- new_job = self.class.new(app, temp_object, meta, url_attrs)
365
+ new_job = dup
366
+ new_job.steps = []
348
367
  new_job.fetch!(uid)
349
368
  new_job.next_step_index = 1
350
369
  new_job
@@ -377,36 +396,14 @@ module Dragonfly
377
396
  steps.select{|s| s.is_a?(Process) }
378
397
  end
379
398
 
380
- def encode_step
381
- last_step_of_type(Encode)
382
- end
383
-
384
399
  def step_types
385
400
  steps.map{|s| s.class.step_name }
386
401
  end
387
402
 
388
403
  # Misc
389
404
 
390
- def store(opts={})
391
- temp_object = result
392
- app.store(temp_object, opts_for_store.merge(opts).merge(:meta => temp_object.meta))
393
- end
394
-
395
405
  def inspect
396
- "<Dragonfly::Job app=#{app.name.inspect}, steps=#{steps.inspect}, temp_object=#{temp_object.inspect}, steps applied:#{applied_steps.length}/#{steps.length} >"
397
- end
398
-
399
- def update(content, new_meta)
400
- if new_meta
401
- new_meta.merge!(new_meta.delete(:meta)) if new_meta[:meta] # legacy data etc. may have nested meta hash - deprecate gracefully here
402
- end
403
- old_meta = temp_object ? temp_object.meta : {}
404
- self.temp_object = TempObject.new(content, old_meta.merge(new_meta || {}))
405
- end
406
-
407
- def close
408
- previous_temp_objects.each{|temp_object| temp_object.close }
409
- temp_object.close if temp_object
406
+ "<Dragonfly::Job app=#{app.name.inspect}, steps=#{steps.inspect}, content=#{content.inspect}, steps applied:#{applied_steps.length}/#{steps.length} >"
410
407
  end
411
408
 
412
409
  protected
@@ -418,25 +415,12 @@ module Dragonfly
418
415
 
419
416
  def result
420
417
  apply
421
- temp_object || raise(NoContent, "Job has not been initialized with content. Need to fetch first?")
418
+ content
422
419
  end
423
420
 
424
- def attributes_for_url
425
- attrs = url_attrs.slice(*server.params_in_url)
426
- attrs[:format] = (attrs[:format] || (url_attrs.ext if app.trust_file_extensions)).to_s if server.params_in_url.include?('format')
427
- attrs.delete_if{|k, v| v.blank? }
428
- attrs
429
- end
430
-
431
- attr_reader :previous_temp_objects
432
-
433
421
  def last_step_of_type(type)
434
422
  steps.select{|s| s.is_a?(type) }.last
435
423
  end
436
424
 
437
- def opts_for_store
438
- {:mime_type => mime_type}
439
- end
440
-
441
425
  end
442
426
  end