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.

Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -4
  4. data/History.md +17 -0
  5. data/README.md +6 -2
  6. data/Rakefile +1 -0
  7. data/dragonfly.gemspec +17 -1
  8. data/lib/dragonfly/app.rb +10 -1
  9. data/lib/dragonfly/file_data_store.rb +1 -1
  10. data/lib/dragonfly/image_magick/plugin.rb +3 -2
  11. data/lib/dragonfly/job.rb +5 -178
  12. data/lib/dragonfly/job/fetch.rb +19 -0
  13. data/lib/dragonfly/job/fetch_file.rb +27 -0
  14. data/lib/dragonfly/job/fetch_url.rb +75 -0
  15. data/lib/dragonfly/job/generate.rb +27 -0
  16. data/lib/dragonfly/job/process.rb +27 -0
  17. data/lib/dragonfly/job/step.rb +44 -0
  18. data/lib/dragonfly/model/attachment.rb +0 -2
  19. data/lib/dragonfly/model/class_methods.rb +5 -0
  20. data/lib/dragonfly/rails/images.rb +1 -0
  21. data/lib/dragonfly/response.rb +11 -2
  22. data/lib/dragonfly/routed_endpoint.rb +15 -5
  23. data/lib/dragonfly/serializer.rb +2 -2
  24. data/lib/dragonfly/shell.rb +28 -5
  25. data/lib/dragonfly/version.rb +1 -1
  26. data/spec/dragonfly/file_data_store_spec.rb +29 -32
  27. data/spec/dragonfly/job/fetch_file_spec.rb +26 -0
  28. data/spec/dragonfly/job/fetch_spec.rb +26 -0
  29. data/spec/dragonfly/job/fetch_url_spec.rb +123 -0
  30. data/spec/dragonfly/job/generate_spec.rb +28 -0
  31. data/spec/dragonfly/job/process_spec.rb +28 -0
  32. data/spec/dragonfly/job_endpoint_spec.rb +17 -0
  33. data/spec/dragonfly/job_spec.rb +0 -187
  34. data/spec/dragonfly/model/model_spec.rb +27 -12
  35. data/spec/dragonfly/routed_endpoint_spec.rb +69 -28
  36. data/spec/dragonfly/shell_spec.rb +2 -2
  37. data/spec/support/simple_matchers.rb +1 -1
  38. metadata +43 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e67b985fbe6f3f97fc92af0803738713e5dcabae
4
- data.tar.gz: 2f2587a40ef4dd9a431e20760cf8ec94530836d0
3
+ metadata.gz: f679f5471b494a363b6ad8b63abe134ab56169e0
4
+ data.tar.gz: 16e5bddb9fabf32fe9f494025aa1d9ec052f9421
5
5
  SHA512:
6
- metadata.gz: ada62ec2fad0a91f4a8131d8b3ea53ee38631f5bde95f02e3eb30a094895ed744d4e8a861e40a1ea9fa31a9d3cbd7f7ed4ba0e87c9ed68c407363f391cb7cb65
7
- data.tar.gz: 90753f8280e3f8e29e4c6de826b5f5d0dc20d2f71df6a239bb05e6e75ac00f23dfeb6c4985140ef319bfba4913a7975292dc65a1910b481b64de03b61dc05650
6
+ metadata.gz: ce1fb089fa71ad9f0ac5ba3a2841de04510c1a9241a99a404be6886a62a1574a594c3fb07efe629e66528d8fdb92b973e67f1f6db4328506cebd6fbec108ba8b
7
+ data.tar.gz: e53fb3a2d1da7c4cd64ab58ca10f4fa39f3167da1a10c7273f36e8ba65e3b142c2df8e29095d06cef1d54d4de2e95be83e9f6f86d52ad1dd5ebbc91e274b85ba
data/.gitignore CHANGED
@@ -7,3 +7,4 @@ Gemfile.lock
7
7
  .s3_spec.yml
8
8
  ***.rbc
9
9
  dragonfly.log
10
+ _site
data/.travis.yml CHANGED
@@ -4,8 +4,5 @@ rvm:
4
4
  - "1.9.2"
5
5
  - "1.9.3"
6
6
  - "2.0.0"
7
- - jruby-18mode # JRuby in 1.8 mode
8
- - jruby-19mode # JRuby in 1.9 mode
9
- - rbx-18mode
10
- - rbx-19mode
7
+ - "jruby"
11
8
  script: bundle exec rspec spec
data/History.md CHANGED
@@ -1,3 +1,20 @@
1
+ 1.0.1 (2013-11-28)
2
+ ===================
3
+ Changes
4
+ -------
5
+ - FileDataStore doesn't use hours_minutes_seconds in its path - it uses a random string instead (12_15_59_saf4fs_file.png -> sdf4c2G_file.png)
6
+
7
+ Features
8
+ --------
9
+ - model attribute `xxx_changed?` method (useful e.g. in validations)
10
+
11
+ Fixes
12
+ -----
13
+ - proper support for Ruby 1.8.7 and JRuby (version 1.7.8)
14
+ - routed endpoints can deal with returned `Attachment` objects (rather than returned `Job` objects) and return 404 if the endpoint proc returns nil
15
+ - default Content-Disposition header doesn't url-encode filename unless the request is from IE
16
+ - `fetch_url` deals with urls that redirect to https (previously was blowing up)
17
+
1
18
  1.0.0 (2013-11-24)
2
19
  ===================
3
20
  Changes
data/README.md CHANGED
@@ -55,8 +55,12 @@ Require with
55
55
  require 'dragonfly'
56
56
  ```
57
57
 
58
- Plugins and Add-ons
59
- ===================
58
+ Ruby Versions
59
+ =============
60
+ Dragonfly has been tested with ruby versions 1.8.7, 1.9.2, 1.9.3, 2.0.0 and jruby 1.7.8.
61
+
62
+ Plugins / add-ons
63
+ =================
60
64
  See [the Add-ons wiki](http://github.com/markevans/dragonfly/wiki/Dragonfly-add-ons).
61
65
 
62
66
  Please feel free to contribute!!
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/dragonfly.gemspec CHANGED
@@ -24,10 +24,26 @@ Gem::Specification.new do |spec|
24
24
  spec.add_runtime_dependency("rack", [">= 0"])
25
25
  spec.add_runtime_dependency("multi_json", ["~> 1.0"])
26
26
 
27
- spec.add_development_dependency("activemodel")
28
27
  spec.add_development_dependency("rspec", ["~> 2.5"])
29
28
  spec.add_development_dependency("webmock")
29
+ if RUBY_VERSION < '1.9.3'
30
+ spec.add_development_dependency("activemodel", '~> 3.2')
31
+ else
32
+ spec.add_development_dependency("activemodel")
33
+ end
30
34
  if RUBY_PLATFORM == "java"
31
35
  spec.add_development_dependency("jruby-openssl")
32
36
  end
37
+ spec.post_install_message =<<-POST_INSTALL_MESSAGE
38
+ ================================================================================
39
+
40
+ Please check the documentation at <http://markevans.github.io/dragonfly/>.
41
+
42
+ --------------------------------------------------------------------------------
43
+
44
+ DEPRECATED: dragonfly/rails/images is now deprecated.
45
+ Please refer to <http://markevans.github.io/dragonfly/rails/> for instructions to setup
46
+ with Rails
47
+ --------------------------------------------------------------------------------
48
+ POST_INSTALL_MESSAGE
33
49
  end
data/lib/dragonfly/app.rb CHANGED
@@ -207,7 +207,7 @@ module Dragonfly
207
207
 
208
208
  def ext_for(mime_type)
209
209
  return 'txt' if mime_type == 'text/plain'
210
- ext = mime_types.key(mime_type)
210
+ ext = key_for(mime_types, mime_type)
211
211
  ext.tr('.', '') if ext
212
212
  end
213
213
 
@@ -279,5 +279,14 @@ module Dragonfly
279
279
  '.' + format.to_s.downcase.sub(/^.*\./,'')
280
280
  end
281
281
 
282
+ def key_for(hash, value)
283
+ if hash.respond_to?(:key)
284
+ hash.key(value)
285
+ else
286
+ hash.each {|k, v| return k if v == value }
287
+ nil
288
+ end
289
+ end
290
+
282
291
  end
283
292
  end
@@ -177,7 +177,7 @@ module Dragonfly
177
177
 
178
178
  def relative_path_for(filename)
179
179
  time = Time.now
180
- "#{time.strftime '%Y/%m/%d/%H_%M_%S'}_#{time.usec.to_s(36)}_#{filename.gsub(/[^\w.]+/,'_')}"
180
+ "#{time.strftime '%Y/%m/%d/'}#{rand(1e15).to_s(36)}_#{filename.gsub(/[^\w.]+/,'_')}"
181
181
  end
182
182
 
183
183
  def purge_empty_directories(path)
@@ -69,9 +69,10 @@ module Dragonfly
69
69
  end
70
70
 
71
71
  # Extra methods
72
- app.define :identify do |args=""|
72
+ app.define :identify do |*args|
73
+ cli_args = args.first # because ruby 1.8.7 can't deal with default args in blocks
73
74
  shell_eval do |path|
74
- "#{app.env[:identify_command]} #{args} #{path}"
75
+ "#{app.env[:identify_command]} #{cli_args} #{path}"
75
76
  end
76
77
  end
77
78
 
data/lib/dragonfly/job.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  require 'forwardable'
2
2
  require 'digest/sha1'
3
- require 'uri'
4
- require 'open-uri'
5
- require 'pathname'
6
- require 'base64'
7
3
  require 'dragonfly/serializer'
8
4
  require 'dragonfly/content'
9
5
  require 'dragonfly/url_attributes'
@@ -27,180 +23,11 @@ module Dragonfly
27
23
  :analyse, :shell_eval, :store,
28
24
  :b64_data
29
25
 
30
- class Step
31
-
32
- class << self
33
- # Dragonfly::Job::Fetch -> 'Fetch'
34
- def basename
35
- @basename ||= name.split('::').last
36
- end
37
- # Dragonfly::Job::Fetch -> :fetch
38
- def step_name
39
- @step_name ||= basename.gsub(/[A-Z]/){ "_#{$&.downcase}" }.sub('_','').to_sym
40
- end
41
- # Dragonfly::Job::Fetch -> 'f'
42
- def abbreviation
43
- @abbreviation ||= basename.scan(/[A-Z]/).join.downcase
44
- end
45
- end
46
-
47
- def initialize(job, *args)
48
- @job, @args = job, args
49
- init
50
- end
51
-
52
- def init # To be overridden
53
- end
54
-
55
- attr_reader :job, :args
56
-
57
- def app
58
- job.app
59
- end
60
-
61
- def to_a
62
- [self.class.abbreviation, *args]
63
- end
64
-
65
- def inspect
66
- "#{self.class.step_name}(#{args.map{|a| a.inspect }.join(', ')})"
67
- end
68
-
69
- end
70
-
71
- class Fetch < Step
72
- class NotFound < RuntimeError; end
73
-
74
- def uid
75
- args.first
76
- end
77
-
78
- def apply
79
- content, meta = app.datastore.read(uid)
80
- raise NotFound, "uid #{uid} not found" if content.nil?
81
- job.content.update(content, meta)
82
- end
83
- end
84
-
85
- class Process < Step
86
- def init
87
- processor.update_url(job.url_attributes, *arguments) if processor.respond_to?(:update_url)
88
- end
89
-
90
- def name
91
- args.first.to_sym
92
- end
93
-
94
- def arguments
95
- args[1..-1]
96
- end
97
-
98
- def processor
99
- @processor ||= app.get_processor(name)
100
- end
101
-
102
- def apply
103
- processor.call(job.content, *arguments)
104
- end
105
- end
106
-
107
- class Generate < Step
108
- def init
109
- generator.update_url(job.url_attributes, *arguments) if generator.respond_to?(:update_url)
110
- end
111
-
112
- def name
113
- args.first
114
- end
115
-
116
- def generator
117
- @generator ||= app.get_generator(name)
118
- end
119
-
120
- def arguments
121
- args[1..-1]
122
- end
123
-
124
- def apply
125
- generator.call(job.content, *arguments)
126
- end
127
- end
128
-
129
- class FetchFile < Step
130
- def initialize(job, path)
131
- super(job, path.to_s)
132
- end
133
- def init
134
- job.url_attributes.name = filename
135
- end
136
-
137
- def path
138
- @path ||= File.expand_path(args.first)
139
- end
140
-
141
- def filename
142
- @filename ||= File.basename(path)
143
- end
144
-
145
- def apply
146
- job.content.update(Pathname.new(path), 'name' => filename)
147
- end
148
- end
149
-
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
-
159
- def init
160
- job.url_attributes.name = filename
161
- end
162
-
163
- def uri
164
- args.first
165
- end
166
-
167
- def url
168
- @url ||= uri =~ /^\w+:/ ? uri : "http://#{uri}"
169
- end
170
-
171
- def filename
172
- return if data_uri?
173
- @filename ||= URI.parse(url).path[/[^\/]+$/]
174
- end
175
-
176
- def data_uri?
177
- uri =~ /^data:/
178
- end
179
-
180
- def apply
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"
201
- end
202
- end
203
- end
26
+ require 'dragonfly/job/fetch'
27
+ require 'dragonfly/job/fetch_file'
28
+ require 'dragonfly/job/fetch_url'
29
+ require 'dragonfly/job/generate'
30
+ require 'dragonfly/job/process'
204
31
 
205
32
  STEPS = [
206
33
  Fetch,
@@ -0,0 +1,19 @@
1
+ require 'dragonfly/job/step'
2
+
3
+ module Dragonfly
4
+ class Job
5
+ class Fetch < Step
6
+ class NotFound < RuntimeError; end
7
+
8
+ def uid
9
+ args.first
10
+ end
11
+
12
+ def apply
13
+ content, meta = app.datastore.read(uid)
14
+ raise NotFound, "uid #{uid} not found" if content.nil?
15
+ job.content.update(content, meta)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'pathname'
2
+ require 'dragonfly/job/step'
3
+
4
+ module Dragonfly
5
+ class Job
6
+ class FetchFile < Step
7
+ def initialize(job, path)
8
+ super(job, path.to_s)
9
+ end
10
+ def init
11
+ job.url_attributes.name = filename
12
+ end
13
+
14
+ def path
15
+ @path ||= File.expand_path(args.first)
16
+ end
17
+
18
+ def filename
19
+ @filename ||= File.basename(path)
20
+ end
21
+
22
+ def apply
23
+ job.content.update(Pathname.new(path), 'name' => filename)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,75 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'base64'
4
+ require 'dragonfly/job/step'
5
+
6
+ module Dragonfly
7
+ class Job
8
+ class FetchUrl < Step
9
+
10
+ class ErrorResponse < RuntimeError
11
+ def initialize(status, body)
12
+ @status, @body = status, body
13
+ end
14
+ attr_reader :status, :body
15
+ end
16
+ class CannotHandle < RuntimeError; end
17
+ class TooManyRedirects < RuntimeError; end
18
+
19
+ def init
20
+ job.url_attributes.name = filename
21
+ end
22
+
23
+ def uri
24
+ args.first
25
+ end
26
+
27
+ def url
28
+ @url ||= uri =~ /^\w+:/ ? uri : "http://#{uri}"
29
+ end
30
+
31
+ def filename
32
+ return if data_uri?
33
+ @filename ||= URI.parse(url).path[/[^\/]+$/]
34
+ end
35
+
36
+ def data_uri?
37
+ uri =~ /^data:/
38
+ end
39
+
40
+ def apply
41
+ if data_uri?
42
+ update_from_data_uri
43
+ else
44
+ data = get(URI.escape(url))
45
+ job.content.update(data, 'name' => filename)
46
+ end
47
+ end
48
+
49
+ def get(url, redirect_limit=10)
50
+ raise TooManyRedirects, "url #{url} redirected too many times" if redirect_limit == 0
51
+ response = Net::HTTP.get_response(URI.parse(url))
52
+ case response
53
+ when Net::HTTPSuccess then response.body || ""
54
+ when Net::HTTPRedirection then get(response['location'], redirect_limit-1)
55
+ else
56
+ response.error!
57
+ end
58
+ rescue Net::HTTPExceptions => e
59
+ raise ErrorResponse.new(e.response.code.to_i, e.response.body)
60
+ end
61
+
62
+ def update_from_data_uri
63
+ mime_type, b64_data = uri.scan(/^data:([^;]+);base64,(.*)$/)[0]
64
+ if mime_type && b64_data
65
+ data = Base64.decode64(b64_data)
66
+ ext = app.ext_for(mime_type)
67
+ job.content.update(data, 'name' => "file.#{ext}")
68
+ else
69
+ raise CannotHandle, "fetch_url can only deal with base64-encoded data uris with specified content type"
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end