bteitelb-paperclip 2.3.1.13 → 2.3.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +2 -2
- data/lib/paperclip.rb +14 -18
- data/lib/paperclip/attachment.rb +125 -46
- data/lib/paperclip/interpolations.rb +17 -17
- data/lib/paperclip/iostream.rb +1 -2
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +3 -2
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +6 -6
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +3 -5
- data/lib/paperclip/storage.rb +9 -13
- data/lib/paperclip/thumbnail.rb +0 -2
- data/test/attachment_test.rb +38 -22
- data/test/helper.rb +1 -1
- data/test/iostream_test.rb +2 -9
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -1
- data/test/matchers/validate_attachment_presence_matcher_test.rb +1 -3
- data/test/matchers/validate_attachment_size_matcher_test.rb +0 -1
- data/test/paperclip_test.rb +41 -12
- data/test/storage_test.rb +0 -27
- data/test/thumbnail_test.rb +1 -1
- metadata +1 -2
- data/lib/paperclip/style.rb +0 -90
data/Rakefile
CHANGED
|
@@ -75,8 +75,8 @@ spec = Gem::Specification.new do |s|
|
|
|
75
75
|
s.extra_rdoc_files = FileList["README*"].to_a
|
|
76
76
|
s.rdoc_options << '--line-numbers' << '--inline-source'
|
|
77
77
|
s.requirements << "ImageMagick"
|
|
78
|
-
s.add_development_dependency 'shoulda'
|
|
79
|
-
s.add_development_dependency 'jferris-mocha', '
|
|
78
|
+
s.add_development_dependency 'thoughtbot-shoulda'
|
|
79
|
+
s.add_development_dependency 'jferris-mocha', '= 0.9.5.0.1241126838'
|
|
80
80
|
s.add_development_dependency 'aws-s3'
|
|
81
81
|
s.add_development_dependency 'sqlite3-ruby'
|
|
82
82
|
s.add_development_dependency 'activerecord'
|
data/lib/paperclip.rb
CHANGED
|
@@ -34,7 +34,6 @@ require 'paperclip/processor'
|
|
|
34
34
|
require 'paperclip/thumbnail'
|
|
35
35
|
require 'paperclip/storage'
|
|
36
36
|
require 'paperclip/interpolations'
|
|
37
|
-
require 'paperclip/style'
|
|
38
37
|
require 'paperclip/attachment'
|
|
39
38
|
if defined? RAILS_ROOT
|
|
40
39
|
Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
|
|
@@ -240,7 +239,7 @@ module Paperclip
|
|
|
240
239
|
|
|
241
240
|
validates_each(name) do |record, attr, value|
|
|
242
241
|
attachment = record.attachment_for(name)
|
|
243
|
-
attachment.send(:flush_errors)
|
|
242
|
+
attachment.send(:flush_errors) unless attachment.valid?
|
|
244
243
|
end
|
|
245
244
|
end
|
|
246
245
|
|
|
@@ -258,13 +257,13 @@ module Paperclip
|
|
|
258
257
|
max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
|
|
259
258
|
range = (min..max)
|
|
260
259
|
message = options[:message] || "file size must be between :min and :max bytes."
|
|
261
|
-
message = message.gsub(/:min/, min.to_s).gsub(/:max/, max.to_s)
|
|
262
260
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
261
|
+
attachment_definitions[name][:validations] << [:size, {:min => min,
|
|
262
|
+
:max => max,
|
|
263
|
+
:range => range,
|
|
264
|
+
:message => message,
|
|
265
|
+
:if => options[:if],
|
|
266
|
+
:unless => options[:unless]}]
|
|
268
267
|
end
|
|
269
268
|
|
|
270
269
|
# Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
|
|
@@ -282,10 +281,9 @@ module Paperclip
|
|
|
282
281
|
# * +unless+: Same as +if+ but validates if lambda or method returns false.
|
|
283
282
|
def validates_attachment_presence name, options = {}
|
|
284
283
|
message = options[:message] || "must be set."
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
:unless => options[:unless]
|
|
284
|
+
attachment_definitions[name][:validations] << [:presence, {:message => message,
|
|
285
|
+
:if => options[:if],
|
|
286
|
+
:unless => options[:unless]}]
|
|
289
287
|
end
|
|
290
288
|
|
|
291
289
|
# Places ActiveRecord-style validations on the content type of the file
|
|
@@ -305,12 +303,10 @@ module Paperclip
|
|
|
305
303
|
# model, content_type validation will work _ONLY upon assignment_ and
|
|
306
304
|
# re-validation after the instance has been reloaded will always succeed.
|
|
307
305
|
def validates_attachment_content_type name, options = {}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
end
|
|
313
|
-
end
|
|
306
|
+
attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
|
|
307
|
+
:message => options[:message],
|
|
308
|
+
:if => options[:if],
|
|
309
|
+
:unless => options[:unless]}]
|
|
314
310
|
end
|
|
315
311
|
|
|
316
312
|
# Returns the attachment definitions defined by each call to
|
data/lib/paperclip/attachment.rb
CHANGED
|
@@ -9,19 +9,18 @@ module Paperclip
|
|
|
9
9
|
|
|
10
10
|
def self.default_options
|
|
11
11
|
@default_options ||= {
|
|
12
|
-
:url
|
|
13
|
-
:path
|
|
14
|
-
:styles
|
|
15
|
-
:
|
|
16
|
-
:
|
|
17
|
-
:
|
|
18
|
-
:
|
|
19
|
-
:
|
|
20
|
-
:whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
|
|
12
|
+
:url => "/system/:attachment/:id/:style/:filename",
|
|
13
|
+
:path => ":rails_root/public:url",
|
|
14
|
+
:styles => {},
|
|
15
|
+
:default_url => "/:attachment/:style/missing.png",
|
|
16
|
+
:default_style => :original,
|
|
17
|
+
:validations => [],
|
|
18
|
+
:storage => :filesystem,
|
|
19
|
+
:whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
|
|
21
20
|
}
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :
|
|
23
|
+
attr_reader :name, :instance, :styles, :default_style, :convert_options, :queued_for_write, :options
|
|
25
24
|
|
|
26
25
|
# Creates an Attachment object. +name+ is the name of the attachment,
|
|
27
26
|
# +instance+ is the ActiveRecord object instance it's attached to, and
|
|
@@ -37,13 +36,14 @@ module Paperclip
|
|
|
37
36
|
@path = options[:path]
|
|
38
37
|
@path = @path.call(self) if @path.is_a?(Proc)
|
|
39
38
|
@styles = options[:styles]
|
|
40
|
-
@
|
|
39
|
+
@styles = @styles.call(self) if @styles.is_a?(Proc)
|
|
41
40
|
@default_url = options[:default_url]
|
|
41
|
+
@validations = options[:validations]
|
|
42
42
|
@default_style = options[:default_style]
|
|
43
43
|
@storage = options[:storage]
|
|
44
44
|
@whiny = options[:whiny_thumbnails] || options[:whiny]
|
|
45
|
-
@convert_options = options[:convert_options]
|
|
46
|
-
@processors = options[:processors]
|
|
45
|
+
@convert_options = options[:convert_options] || {}
|
|
46
|
+
@processors = options[:processors] || [:thumbnail]
|
|
47
47
|
@options = options
|
|
48
48
|
@queued_for_delete = []
|
|
49
49
|
@queued_for_write = {}
|
|
@@ -52,29 +52,18 @@ module Paperclip
|
|
|
52
52
|
@validation_errors = nil
|
|
53
53
|
@dirty = false
|
|
54
54
|
|
|
55
|
+
normalize_style_definition
|
|
55
56
|
initialize_storage
|
|
56
57
|
end
|
|
57
|
-
|
|
58
|
-
def styles
|
|
59
|
-
unless @normalized_styles
|
|
60
|
-
@normalized_styles = {}
|
|
61
|
-
(@styles.respond_to?(:call) ? @styles.call(self) : @styles).each do |name, args|
|
|
62
|
-
@normalized_styles[name] = Paperclip::Style.new(name, args, self)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
@normalized_styles
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def processors
|
|
69
|
-
@processors.respond_to?(:call) ? @processors.call(instance) : @processors
|
|
70
|
-
end
|
|
71
58
|
|
|
72
59
|
# What gets called when you call instance.attachment = File. It clears
|
|
73
|
-
# errors, assigns attributes,
|
|
60
|
+
# errors, assigns attributes, processes the file, and runs validations. It
|
|
74
61
|
# also queues up the previous file for deletion, to be flushed away on
|
|
75
62
|
# #save of its host. In addition to form uploads, you can also assign
|
|
76
63
|
# another Paperclip attachment:
|
|
77
64
|
# new_user.avatar = old_user.avatar
|
|
65
|
+
# If the file that is assigned is not valid, the processing (i.e.
|
|
66
|
+
# thumbnailing, etc) will NOT be run.
|
|
78
67
|
def assign uploaded_file
|
|
79
68
|
ensure_required_accessors!
|
|
80
69
|
|
|
@@ -104,7 +93,7 @@ module Paperclip
|
|
|
104
93
|
|
|
105
94
|
@dirty = true
|
|
106
95
|
|
|
107
|
-
post_process
|
|
96
|
+
post_process if valid?
|
|
108
97
|
|
|
109
98
|
# Reset the file size if the original file was reprocessed.
|
|
110
99
|
instance_write(:file_size, @queued_for_write[:original].size.to_i)
|
|
@@ -126,6 +115,7 @@ module Paperclip
|
|
|
126
115
|
end
|
|
127
116
|
ensure
|
|
128
117
|
uploaded_file.close if close_uploaded_file
|
|
118
|
+
validate
|
|
129
119
|
end
|
|
130
120
|
|
|
131
121
|
# Returns the public URL of the attachment, with a given style. Note that
|
|
@@ -135,8 +125,8 @@ module Paperclip
|
|
|
135
125
|
# security, however, for performance reasons. set
|
|
136
126
|
# include_updated_timestamp to false if you want to stop the attachment
|
|
137
127
|
# update time appended to the url
|
|
138
|
-
def url
|
|
139
|
-
url = original_filename.nil? ? interpolate(@default_url,
|
|
128
|
+
def url style = default_style, include_updated_timestamp = true
|
|
129
|
+
url = original_filename.nil? ? interpolate(@default_url, style) : interpolate(@url, style)
|
|
140
130
|
include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url
|
|
141
131
|
end
|
|
142
132
|
|
|
@@ -144,13 +134,19 @@ module Paperclip
|
|
|
144
134
|
# file is stored in the filesystem the path refers to the path of the file
|
|
145
135
|
# on disk. If the file is stored in S3, the path is the "key" part of the
|
|
146
136
|
# URL, and the :bucket option refers to the S3 bucket.
|
|
147
|
-
def path
|
|
148
|
-
original_filename.nil? ? nil : interpolate(@path,
|
|
137
|
+
def path style = default_style
|
|
138
|
+
original_filename.nil? ? nil : interpolate(@path, style)
|
|
149
139
|
end
|
|
150
140
|
|
|
151
141
|
# Alias to +url+
|
|
152
|
-
def to_s
|
|
153
|
-
url(
|
|
142
|
+
def to_s style = nil
|
|
143
|
+
url(style)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Returns true if there are no errors on this attachment.
|
|
147
|
+
def valid?
|
|
148
|
+
validate
|
|
149
|
+
errors.empty?
|
|
154
150
|
end
|
|
155
151
|
|
|
156
152
|
# Returns an array containing the errors on this attachment.
|
|
@@ -166,10 +162,15 @@ module Paperclip
|
|
|
166
162
|
# Saves the file, if there are no errors. If there are, it flushes them to
|
|
167
163
|
# the instance's errors and returns false, cancelling the save.
|
|
168
164
|
def save
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
165
|
+
if valid?
|
|
166
|
+
flush_deletes
|
|
167
|
+
flush_writes
|
|
168
|
+
@dirty = false
|
|
169
|
+
true
|
|
170
|
+
else
|
|
171
|
+
flush_errors
|
|
172
|
+
false
|
|
173
|
+
end
|
|
173
174
|
end
|
|
174
175
|
|
|
175
176
|
# Clears out the attachment. Has the same effect as previously assigning
|
|
@@ -178,6 +179,7 @@ module Paperclip
|
|
|
178
179
|
def clear
|
|
179
180
|
queue_existing_for_delete
|
|
180
181
|
@errors = {}
|
|
182
|
+
@validation_errors = nil
|
|
181
183
|
end
|
|
182
184
|
|
|
183
185
|
# Destroys the attachment. Has the same effect as previously assigning
|
|
@@ -309,6 +311,82 @@ module Paperclip
|
|
|
309
311
|
file.nil? || (file.respond_to?(:original_filename) && file.respond_to?(:content_type))
|
|
310
312
|
end
|
|
311
313
|
|
|
314
|
+
def validate #:nodoc:
|
|
315
|
+
unless @validation_errors
|
|
316
|
+
@validation_errors = @validations.inject({}) do |errors, validation|
|
|
317
|
+
name, options = validation
|
|
318
|
+
errors[name] = send(:"validate_#{name}", options) if allow_validation?(options)
|
|
319
|
+
errors
|
|
320
|
+
end
|
|
321
|
+
@validation_errors.reject!{|k,v| v == nil }
|
|
322
|
+
@errors.merge!(@validation_errors)
|
|
323
|
+
end
|
|
324
|
+
@validation_errors
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def allow_validation? options #:nodoc:
|
|
328
|
+
(options[:if].nil? || check_guard(options[:if])) && (options[:unless].nil? || !check_guard(options[:unless]))
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def check_guard guard #:nodoc:
|
|
332
|
+
if guard.respond_to? :call
|
|
333
|
+
guard.call(instance)
|
|
334
|
+
elsif ! guard.blank?
|
|
335
|
+
instance.send(guard.to_s)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def validate_size options #:nodoc:
|
|
340
|
+
if file? && !options[:range].include?(size.to_i)
|
|
341
|
+
options[:message].gsub(/:min/, options[:min].to_s).gsub(/:max/, options[:max].to_s)
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def validate_presence options #:nodoc:
|
|
346
|
+
options[:message] unless file?
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def validate_content_type options #:nodoc:
|
|
350
|
+
valid_types = [options[:content_type]].flatten
|
|
351
|
+
unless original_filename.blank?
|
|
352
|
+
unless valid_types.blank?
|
|
353
|
+
content_type = instance_read(:content_type)
|
|
354
|
+
unless valid_types.any?{|t| content_type.nil? || t === content_type }
|
|
355
|
+
options[:message] || "is not one of the allowed file types."
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def normalize_style_definition #:nodoc:
|
|
362
|
+
@styles.each do |name, args|
|
|
363
|
+
unless args.is_a? Hash
|
|
364
|
+
dimensions, format = [args, nil].flatten[0..1]
|
|
365
|
+
format = nil if format.blank?
|
|
366
|
+
@styles[name] = {
|
|
367
|
+
:processors => @processors,
|
|
368
|
+
:geometry => dimensions,
|
|
369
|
+
:format => format,
|
|
370
|
+
:whiny => @whiny,
|
|
371
|
+
:convert_options => extra_options_for(name)
|
|
372
|
+
}
|
|
373
|
+
else
|
|
374
|
+
@styles[name] = {
|
|
375
|
+
:processors => @processors,
|
|
376
|
+
:whiny => @whiny,
|
|
377
|
+
:convert_options => extra_options_for(name)
|
|
378
|
+
}.merge(@styles[name])
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def solidify_style_definitions #:nodoc:
|
|
384
|
+
@styles.each do |name, args|
|
|
385
|
+
@styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
|
|
386
|
+
@styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
312
390
|
def initialize_storage #:nodoc:
|
|
313
391
|
@storage_module = Paperclip::Storage.const_get(@storage.to_s.capitalize)
|
|
314
392
|
self.extend(@storage_module)
|
|
@@ -325,6 +403,7 @@ module Paperclip
|
|
|
325
403
|
|
|
326
404
|
def post_process #:nodoc:
|
|
327
405
|
return if @queued_for_write[:original].nil?
|
|
406
|
+
solidify_style_definitions
|
|
328
407
|
return if fire_events(:before)
|
|
329
408
|
post_process_styles
|
|
330
409
|
return if fire_events(:after)
|
|
@@ -340,11 +419,11 @@ module Paperclip
|
|
|
340
419
|
end
|
|
341
420
|
|
|
342
421
|
def post_process_styles #:nodoc:
|
|
343
|
-
styles.each do |name,
|
|
422
|
+
@styles.each do |name, args|
|
|
344
423
|
begin
|
|
345
|
-
raise RuntimeError.new("Style #{name} has no processors defined.") if
|
|
346
|
-
@queued_for_write[name] =
|
|
347
|
-
Paperclip.processor(processor).make(file,
|
|
424
|
+
raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
|
|
425
|
+
@queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
|
|
426
|
+
Paperclip.processor(processor).make(file, args, self)
|
|
348
427
|
end
|
|
349
428
|
rescue PaperclipError => e
|
|
350
429
|
log("An error was received while processing: #{e.inspect}")
|
|
@@ -353,8 +432,8 @@ module Paperclip
|
|
|
353
432
|
end
|
|
354
433
|
end
|
|
355
434
|
|
|
356
|
-
def interpolate pattern,
|
|
357
|
-
Paperclip::Interpolations.interpolate(pattern, self,
|
|
435
|
+
def interpolate pattern, style = default_style #:nodoc:
|
|
436
|
+
Paperclip::Interpolations.interpolate(pattern, self, style)
|
|
358
437
|
end
|
|
359
438
|
|
|
360
439
|
def mime_type
|
|
@@ -381,7 +460,7 @@ module Paperclip
|
|
|
381
460
|
|
|
382
461
|
def queue_existing_for_delete #:nodoc:
|
|
383
462
|
return unless file?
|
|
384
|
-
@queued_for_delete += [:original,
|
|
463
|
+
@queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
|
|
385
464
|
path(style) if exists?(style)
|
|
386
465
|
end.compact
|
|
387
466
|
instance_write(:file_name, nil)
|
|
@@ -34,30 +34,30 @@ module Paperclip
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
# Returns the filename, the same way as ":basename.:extension" would.
|
|
37
|
-
def filename attachment,
|
|
38
|
-
"#{basename(attachment,
|
|
37
|
+
def filename attachment, style
|
|
38
|
+
"#{basename(attachment, style)}.#{extension(attachment, style)}"
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
# Returns the interpolated URL. Will raise an error if the url itself
|
|
42
42
|
# contains ":url" to prevent infinite recursion. This interpolation
|
|
43
43
|
# is used in the default :path to ease default specifications.
|
|
44
|
-
def url attachment,
|
|
44
|
+
def url attachment, style
|
|
45
45
|
raise InfiniteInterpolationError if attachment.options[:url].include?(":url")
|
|
46
|
-
attachment.url(
|
|
46
|
+
attachment.url(style, false)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
# Returns the timestamp as defined by the <attachment>_updated_at field
|
|
50
|
-
def timestamp attachment,
|
|
50
|
+
def timestamp attachment, style
|
|
51
51
|
attachment.instance_read(:updated_at).to_s
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Returns the RAILS_ROOT constant.
|
|
55
|
-
def rails_root attachment,
|
|
55
|
+
def rails_root attachment, style
|
|
56
56
|
RAILS_ROOT
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
# Returns the RAILS_ENV constant.
|
|
60
|
-
def rails_env attachment,
|
|
60
|
+
def rails_env attachment, style
|
|
61
61
|
RAILS_ENV
|
|
62
62
|
end
|
|
63
63
|
|
|
@@ -65,44 +65,44 @@ module Paperclip
|
|
|
65
65
|
# e.g. "users" for the User class.
|
|
66
66
|
# NOTE: The arguments need to be optional, because some tools fetch
|
|
67
67
|
# all class names. Calling #class will return the expected class.
|
|
68
|
-
def class attachment = nil,
|
|
69
|
-
return super() if attachment.nil? &&
|
|
68
|
+
def class attachment = nil, style = nil
|
|
69
|
+
return super() if attachment.nil? && style.nil?
|
|
70
70
|
attachment.instance.class.to_s.underscore.pluralize
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
# Returns the basename of the file. e.g. "file" for "file.jpg"
|
|
74
|
-
def basename attachment,
|
|
74
|
+
def basename attachment, style
|
|
75
75
|
attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Returns the extension of the file. e.g. "jpg" for "file.jpg"
|
|
79
79
|
# If the style has a format defined, it will return the format instead
|
|
80
80
|
# of the actual extension.
|
|
81
|
-
def extension attachment,
|
|
82
|
-
((style = attachment.styles[
|
|
81
|
+
def extension attachment, style
|
|
82
|
+
((style = attachment.styles[style]) && style[:format]) ||
|
|
83
83
|
File.extname(attachment.original_filename).gsub(/^\.+/, "")
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
# Returns the id of the instance.
|
|
87
|
-
def id attachment,
|
|
87
|
+
def id attachment, style
|
|
88
88
|
attachment.instance.id
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
# Returns the id of the instance in a split path form. e.g. returns
|
|
92
92
|
# 000/001/234 for an id of 1234.
|
|
93
|
-
def id_partition attachment,
|
|
93
|
+
def id_partition attachment, style
|
|
94
94
|
("%09d" % attachment.instance.id).scan(/\d{3}/).join("/")
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# Returns the pluralized form of the attachment name. e.g.
|
|
98
98
|
# "avatars" for an attachment of :avatar
|
|
99
|
-
def attachment attachment,
|
|
99
|
+
def attachment attachment, style
|
|
100
100
|
attachment.name.to_s.downcase.pluralize
|
|
101
101
|
end
|
|
102
102
|
|
|
103
103
|
# Returns the style, or the default style if nil is supplied.
|
|
104
|
-
def style attachment,
|
|
105
|
-
|
|
104
|
+
def style attachment, style
|
|
105
|
+
style || attachment.default_style
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
end
|
data/lib/paperclip/iostream.rb
CHANGED
|
@@ -4,8 +4,7 @@ module IOStream
|
|
|
4
4
|
|
|
5
5
|
# Returns a Tempfile containing the contents of the readable object.
|
|
6
6
|
def to_tempfile
|
|
7
|
-
|
|
8
|
-
tempfile = Paperclip::Tempfile.new(File.basename(name))
|
|
7
|
+
tempfile = Tempfile.new("stream")
|
|
9
8
|
tempfile.binmode
|
|
10
9
|
self.stream_to(tempfile)
|
|
11
10
|
end
|
|
@@ -46,8 +46,9 @@ module Paperclip
|
|
|
46
46
|
types.all? do |type|
|
|
47
47
|
file = StringIO.new(".")
|
|
48
48
|
file.content_type = type
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
attachment = @subject.new.attachment_for(@attachment_name)
|
|
50
|
+
attachment.assign(file)
|
|
51
|
+
attachment.errors[:content_type].nil?
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -30,16 +30,16 @@ module Paperclip
|
|
|
30
30
|
protected
|
|
31
31
|
|
|
32
32
|
def error_when_not_valid?
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
not
|
|
33
|
+
@attachment = @subject.new.send(@attachment_name)
|
|
34
|
+
@attachment.assign(nil)
|
|
35
|
+
not @attachment.errors[:presence].nil?
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def no_error_when_valid?
|
|
39
39
|
@file = StringIO.new(".")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
@attachment = @subject.new.send(@attachment_name)
|
|
41
|
+
@attachment.assign(@file)
|
|
42
|
+
@attachment.errors[:presence].nil?
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -54,11 +54,9 @@ module Paperclip
|
|
|
54
54
|
def passes_validation_with_size(new_size)
|
|
55
55
|
file = StringIO.new(".")
|
|
56
56
|
override_method(file, :size){ new_size }
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
subject.valid?
|
|
61
|
-
subject.errors.on(:"#{@attachment_name}_file_size").blank?
|
|
57
|
+
attachment = @subject.new.attachment_for(@attachment_name)
|
|
58
|
+
attachment.assign(file)
|
|
59
|
+
attachment.errors[:size].nil?
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
def lower_than_low?
|
data/lib/paperclip/storage.rb
CHANGED
|
@@ -20,9 +20,9 @@ module Paperclip
|
|
|
20
20
|
def self.extended base
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def exists?(
|
|
23
|
+
def exists?(style = default_style)
|
|
24
24
|
if original_filename
|
|
25
|
-
File.exist?(path(
|
|
25
|
+
File.exist?(path(style))
|
|
26
26
|
else
|
|
27
27
|
false
|
|
28
28
|
end
|
|
@@ -30,17 +30,17 @@ module Paperclip
|
|
|
30
30
|
|
|
31
31
|
# Returns representation of the data of the file assigned to the given
|
|
32
32
|
# style, in the format most representative of the current storage.
|
|
33
|
-
def to_file
|
|
34
|
-
@queued_for_write[
|
|
33
|
+
def to_file style = default_style
|
|
34
|
+
@queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style))
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def flush_writes #:nodoc:
|
|
38
|
-
@queued_for_write.each do |
|
|
38
|
+
@queued_for_write.each do |style, file|
|
|
39
39
|
file.close
|
|
40
|
-
FileUtils.mkdir_p(File.dirname(path(
|
|
41
|
-
log("saving #{path(
|
|
42
|
-
FileUtils.mv(file.path, path(
|
|
43
|
-
FileUtils.chmod(0644, path(
|
|
40
|
+
FileUtils.mkdir_p(File.dirname(path(style)))
|
|
41
|
+
log("saving #{path(style)}")
|
|
42
|
+
FileUtils.mv(file.path, path(style))
|
|
43
|
+
FileUtils.chmod(0644, path(style))
|
|
44
44
|
end
|
|
45
45
|
@queued_for_write = {}
|
|
46
46
|
end
|
|
@@ -159,10 +159,6 @@ module Paperclip
|
|
|
159
159
|
"#{attachment.s3_protocol}://#{attachment.bucket_name}.s3.amazonaws.com/#{attachment.path(style).gsub(%r{^/}, "")}"
|
|
160
160
|
end
|
|
161
161
|
end
|
|
162
|
-
|
|
163
|
-
def expiring_url(time = 3600)
|
|
164
|
-
AWS::S3::S3Object.url_for(path, bucket_name, :expires_in => time )
|
|
165
|
-
end
|
|
166
162
|
|
|
167
163
|
def bucket_name
|
|
168
164
|
@bucket
|
data/lib/paperclip/thumbnail.rb
CHANGED
|
@@ -12,7 +12,6 @@ module Paperclip
|
|
|
12
12
|
# set, the options will be appended to the convert command upon image conversion
|
|
13
13
|
def initialize file, options = {}, attachment = nil
|
|
14
14
|
super
|
|
15
|
-
|
|
16
15
|
geometry = options[:geometry]
|
|
17
16
|
@file = file
|
|
18
17
|
@crop = geometry[-1,1] == '#'
|
|
@@ -25,7 +24,6 @@ module Paperclip
|
|
|
25
24
|
|
|
26
25
|
@current_format = File.extname(@file.path)
|
|
27
26
|
@basename = File.basename(@file.path, @current_format)
|
|
28
|
-
|
|
29
27
|
end
|
|
30
28
|
|
|
31
29
|
# Returns true if the +target_geometry+ is meant to crop.
|
data/test/attachment_test.rb
CHANGED
|
@@ -14,6 +14,18 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
14
14
|
assert_equal "#{RAILS_ROOT}/public/fake_models/1234/fake", @attachment.path
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
should "call a proc sent to check_guard" do
|
|
18
|
+
@dummy = Dummy.new
|
|
19
|
+
@dummy.expects(:one).returns(:one)
|
|
20
|
+
assert_equal :one, @dummy.avatar.send(:check_guard, lambda{|x| x.one })
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
should "call a method name sent to check_guard" do
|
|
24
|
+
@dummy = Dummy.new
|
|
25
|
+
@dummy.expects(:one).returns(:one)
|
|
26
|
+
assert_equal :one, @dummy.avatar.send(:check_guard, :one)
|
|
27
|
+
end
|
|
28
|
+
|
|
17
29
|
context "Attachment default_options" do
|
|
18
30
|
setup do
|
|
19
31
|
rebuild_model
|
|
@@ -121,7 +133,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
121
133
|
:styles => { :default => ["100x100", :png] },
|
|
122
134
|
:default_style => :default
|
|
123
135
|
@file = StringIO.new("...")
|
|
124
|
-
@file.
|
|
136
|
+
@file.expects(:original_filename).returns("file.jpg")
|
|
125
137
|
end
|
|
126
138
|
should "return the right extension for the path" do
|
|
127
139
|
@attachment.assign(@file)
|
|
@@ -150,6 +162,11 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
150
162
|
should "report the correct options when sent #extra_options_for(:large)" do
|
|
151
163
|
assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
|
|
152
164
|
end
|
|
165
|
+
|
|
166
|
+
before_should "call extra_options_for(:thumb/:large)" do
|
|
167
|
+
Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
|
|
168
|
+
Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
|
|
169
|
+
end
|
|
153
170
|
end
|
|
154
171
|
|
|
155
172
|
context "An attachment with :convert_options that is a proc" do
|
|
@@ -177,6 +194,11 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
177
194
|
should "report the correct options when sent #extra_options_for(:large)" do
|
|
178
195
|
assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
|
|
179
196
|
end
|
|
197
|
+
|
|
198
|
+
before_should "call extra_options_for(:thumb/:large)" do
|
|
199
|
+
Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:thumb)
|
|
200
|
+
Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
|
|
201
|
+
end
|
|
180
202
|
end
|
|
181
203
|
|
|
182
204
|
context "An attachment with :path that is a proc" do
|
|
@@ -245,6 +267,10 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
245
267
|
@attachment = Dummy.new.avatar
|
|
246
268
|
end
|
|
247
269
|
|
|
270
|
+
should "not run the procs immediately" do
|
|
271
|
+
assert_kind_of Proc, @attachment.styles[:normal][:geometry]
|
|
272
|
+
end
|
|
273
|
+
|
|
248
274
|
context "when assigned" do
|
|
249
275
|
setup do
|
|
250
276
|
@file = StringIO.new(".")
|
|
@@ -281,6 +307,10 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
281
307
|
@attachment = Dummy.new.avatar
|
|
282
308
|
end
|
|
283
309
|
|
|
310
|
+
should "not run the proc immediately" do
|
|
311
|
+
assert_kind_of Proc, @attachment.styles[:normal][:processors]
|
|
312
|
+
end
|
|
313
|
+
|
|
284
314
|
context "when assigned" do
|
|
285
315
|
setup do
|
|
286
316
|
@attachment.assign(StringIO.new("."))
|
|
@@ -324,22 +354,19 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
324
354
|
setup { @dummy.avatar = @file }
|
|
325
355
|
|
|
326
356
|
before_should "call #make on all specified processors" do
|
|
327
|
-
Paperclip::Thumbnail.expects(:make).with(any_parameters).returns(@file)
|
|
328
|
-
Paperclip::Test.expects(:make).with(any_parameters).returns(@file)
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
before_should "call #make with the right parameters passed as second argument" do
|
|
332
357
|
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
|
|
333
|
-
Paperclip::Thumbnail.expects(:make).with(
|
|
358
|
+
Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
|
359
|
+
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
|
334
360
|
end
|
|
335
361
|
|
|
336
362
|
before_should "call #make with attachment passed as third argument" do
|
|
337
|
-
|
|
363
|
+
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
|
|
364
|
+
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
|
338
365
|
end
|
|
339
366
|
end
|
|
340
367
|
end
|
|
341
368
|
|
|
342
|
-
context "An attachment with
|
|
369
|
+
context "An attachment with no processors defined" do
|
|
343
370
|
setup do
|
|
344
371
|
rebuild_model :processors => [], :styles => {:something => 1}
|
|
345
372
|
@dummy = Dummy.new
|
|
@@ -350,17 +377,6 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
350
377
|
end
|
|
351
378
|
end
|
|
352
379
|
|
|
353
|
-
context "An attachment without styles and with no processors defined" do
|
|
354
|
-
setup do
|
|
355
|
-
rebuild_model :processors => [], :styles => {}
|
|
356
|
-
@dummy = Dummy.new
|
|
357
|
-
@file = StringIO.new("...")
|
|
358
|
-
end
|
|
359
|
-
should "not raise when assigned to" do
|
|
360
|
-
@dummy.avatar = @file
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
|
|
364
380
|
context "Assigning an attachment with post_process hooks" do
|
|
365
381
|
setup do
|
|
366
382
|
rebuild_model :styles => { :something => "100x100#" }
|
|
@@ -462,6 +478,8 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
462
478
|
@attachment.expects(:valid_assignment?).with(@not_file).returns(true)
|
|
463
479
|
@attachment.expects(:queue_existing_for_delete)
|
|
464
480
|
@attachment.expects(:post_process)
|
|
481
|
+
@attachment.expects(:valid?).returns(true)
|
|
482
|
+
@attachment.expects(:validate)
|
|
465
483
|
@dummy.avatar = @not_file
|
|
466
484
|
end
|
|
467
485
|
|
|
@@ -480,7 +498,6 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
480
498
|
FileUtils.rm_rf("tmp")
|
|
481
499
|
rebuild_model
|
|
482
500
|
@instance = Dummy.new
|
|
483
|
-
@instance.stubs(:id).returns 123
|
|
484
501
|
@attachment = Paperclip::Attachment.new(:avatar, @instance)
|
|
485
502
|
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
|
|
486
503
|
end
|
|
@@ -589,7 +606,6 @@ class AttachmentTest < Test::Unit::TestCase
|
|
|
589
606
|
should "commit the files to disk" do
|
|
590
607
|
[:large, :medium, :small].each do |style|
|
|
591
608
|
io = @attachment.to_file(style)
|
|
592
|
-
# p "in commit to disk test, io is #{io.inspect} and @instance.id is #{@instance.id}"
|
|
593
609
|
assert File.exists?(io)
|
|
594
610
|
assert ! io.is_a?(::Tempfile)
|
|
595
611
|
io.close
|
data/test/helper.rb
CHANGED
data/test/iostream_test.rb
CHANGED
|
@@ -58,15 +58,8 @@ class IOStreamTest < Test::Unit::TestCase
|
|
|
58
58
|
assert @tempfile = @file.to_tempfile
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
should "convert it to a
|
|
62
|
-
assert @tempfile.is_a?(
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
should "have the name be based on the original_filename" do
|
|
66
|
-
name = File.basename(@file.path)
|
|
67
|
-
extension = File.extname(name)
|
|
68
|
-
basename = File.basename(name, extension)
|
|
69
|
-
assert_match %r[^#{Regexp.quote(basename)}.*?#{Regexp.quote(extension)}], File.basename(@tempfile.path)
|
|
61
|
+
should "convert it to a Tempfile" do
|
|
62
|
+
assert @tempfile.is_a?(Tempfile)
|
|
70
63
|
end
|
|
71
64
|
|
|
72
65
|
should "have the Tempfile contain the same data as the file" do
|
|
@@ -3,9 +3,7 @@ require 'test/helper'
|
|
|
3
3
|
class ValidateAttachmentPresenceMatcherTest < Test::Unit::TestCase
|
|
4
4
|
context "validate_attachment_presence" do
|
|
5
5
|
setup do
|
|
6
|
-
reset_table("dummies")
|
|
7
|
-
d.string :avatar_file_name
|
|
8
|
-
end
|
|
6
|
+
reset_table("dummies"){|d| d.string :avatar_file_name }
|
|
9
7
|
@dummy_class = reset_class "Dummy"
|
|
10
8
|
@dummy_class.has_attached_file :avatar
|
|
11
9
|
@matcher = self.class.validate_attachment_presence(:avatar)
|
data/test/paperclip_test.rb
CHANGED
|
@@ -185,23 +185,45 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
185
185
|
should "be valid" do
|
|
186
186
|
assert @dummy.valid?
|
|
187
187
|
end
|
|
188
|
+
|
|
189
|
+
context "then has a validation added that makes it invalid" do
|
|
190
|
+
setup do
|
|
191
|
+
assert @dummy.save
|
|
192
|
+
Dummy.class_eval do
|
|
193
|
+
validates_attachment_content_type :avatar, :content_type => ["text/plain"]
|
|
194
|
+
end
|
|
195
|
+
@dummy2 = Dummy.find(@dummy.id)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
should "be invalid when reloaded" do
|
|
199
|
+
assert ! @dummy2.valid?, @dummy2.errors.inspect
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
should "be able to call #valid? twice without having duplicate errors" do
|
|
203
|
+
@dummy2.avatar.valid?
|
|
204
|
+
first_errors = @dummy2.avatar.errors
|
|
205
|
+
@dummy2.avatar.valid?
|
|
206
|
+
assert_equal first_errors, @dummy2.avatar.errors
|
|
207
|
+
end
|
|
208
|
+
end
|
|
188
209
|
end
|
|
189
210
|
|
|
190
211
|
context "a validation with an if guard clause" do
|
|
191
212
|
setup do
|
|
192
213
|
Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
|
|
193
214
|
@dummy = Dummy.new
|
|
194
|
-
@dummy.stubs(:avatar_file_name).returns(nil)
|
|
195
215
|
end
|
|
196
216
|
|
|
197
217
|
should "attempt validation if the guard returns true" do
|
|
198
218
|
@dummy.expects(:foo).returns(true)
|
|
199
|
-
|
|
219
|
+
@dummy.avatar.expects(:validate_presence).returns(nil)
|
|
220
|
+
@dummy.valid?
|
|
200
221
|
end
|
|
201
222
|
|
|
202
223
|
should "not attempt validation if the guard returns false" do
|
|
203
224
|
@dummy.expects(:foo).returns(false)
|
|
204
|
-
|
|
225
|
+
@dummy.avatar.expects(:validate_presence).never
|
|
226
|
+
@dummy.valid?
|
|
205
227
|
end
|
|
206
228
|
end
|
|
207
229
|
|
|
@@ -209,17 +231,18 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
209
231
|
setup do
|
|
210
232
|
Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
|
|
211
233
|
@dummy = Dummy.new
|
|
212
|
-
@dummy.stubs(:avatar_file_name).returns(nil)
|
|
213
234
|
end
|
|
214
235
|
|
|
215
236
|
should "attempt validation if the guard returns true" do
|
|
216
237
|
@dummy.expects(:foo).returns(false)
|
|
217
|
-
|
|
238
|
+
@dummy.avatar.expects(:validate_presence).returns(nil)
|
|
239
|
+
@dummy.valid?
|
|
218
240
|
end
|
|
219
241
|
|
|
220
242
|
should "not attempt validation if the guard returns false" do
|
|
221
243
|
@dummy.expects(:foo).returns(true)
|
|
222
|
-
|
|
244
|
+
@dummy.avatar.expects(:validate_presence).never
|
|
245
|
+
@dummy.valid?
|
|
223
246
|
end
|
|
224
247
|
end
|
|
225
248
|
|
|
@@ -236,11 +259,11 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
236
259
|
end
|
|
237
260
|
if validation == :presence
|
|
238
261
|
should "have an error on the attachment" do
|
|
239
|
-
assert @dummy.errors.on(:
|
|
262
|
+
assert @dummy.errors.on(:avatar)
|
|
240
263
|
end
|
|
241
264
|
else
|
|
242
265
|
should "not have an error on the attachment" do
|
|
243
|
-
assert_nil @dummy.errors.on(:
|
|
266
|
+
assert_nil @dummy.errors.on(:avatar)
|
|
244
267
|
end
|
|
245
268
|
end
|
|
246
269
|
end
|
|
@@ -250,7 +273,10 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
250
273
|
@dummy.valid?
|
|
251
274
|
end
|
|
252
275
|
should "not have an error when assigned a valid file" do
|
|
253
|
-
|
|
276
|
+
assert ! @dummy.avatar.errors.key?(validation)
|
|
277
|
+
end
|
|
278
|
+
should "not have an error on the attachment" do
|
|
279
|
+
assert_nil @dummy.errors.on(:avatar)
|
|
254
280
|
end
|
|
255
281
|
end
|
|
256
282
|
context "and assigned an invalid file" do
|
|
@@ -259,14 +285,17 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
259
285
|
@dummy.valid?
|
|
260
286
|
end
|
|
261
287
|
should "have an error when assigned a valid file" do
|
|
262
|
-
|
|
288
|
+
assert_not_nil @dummy.avatar.errors[validation]
|
|
289
|
+
end
|
|
290
|
+
should "have an error on the attachment" do
|
|
291
|
+
assert @dummy.errors.on(:avatar)
|
|
263
292
|
end
|
|
264
293
|
end
|
|
265
294
|
end
|
|
266
295
|
end
|
|
267
296
|
|
|
268
297
|
[[:presence, {}, "5k.png", nil],
|
|
269
|
-
[:size, {:in => 1..10240},
|
|
298
|
+
[:size, {:in => 1..10240}, nil, "12k.png"],
|
|
270
299
|
[:size, {:less_than => 10240}, "5k.png", "12k.png"],
|
|
271
300
|
[:size, {:greater_than => 8096}, "12k.png", "5k.png"],
|
|
272
301
|
[:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
|
|
@@ -289,7 +318,7 @@ class PaperclipTest < Test::Unit::TestCase
|
|
|
289
318
|
end
|
|
290
319
|
|
|
291
320
|
should "have a file size min/max error message" do
|
|
292
|
-
assert_match
|
|
321
|
+
assert_match /between 0 and 10240 bytes/, @dummy.errors.on(:avatar)
|
|
293
322
|
end
|
|
294
323
|
end
|
|
295
324
|
end
|
data/test/storage_test.rb
CHANGED
|
@@ -96,33 +96,6 @@ class StorageTest < Test::Unit::TestCase
|
|
|
96
96
|
assert_match %r{^http://something.something.com/avatars/stringio.txt}, @dummy.avatar.url
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
|
-
|
|
100
|
-
context "Generating a url with an expiration" do
|
|
101
|
-
setup do
|
|
102
|
-
AWS::S3::Base.stubs(:establish_connection!)
|
|
103
|
-
rebuild_model :storage => :s3,
|
|
104
|
-
:s3_credentials => {
|
|
105
|
-
:production => { :bucket => "prod_bucket" },
|
|
106
|
-
:development => { :bucket => "dev_bucket" }
|
|
107
|
-
},
|
|
108
|
-
:s3_host_alias => "something.something.com",
|
|
109
|
-
:path => ":attachment/:basename.:extension",
|
|
110
|
-
:url => ":s3_alias_url"
|
|
111
|
-
|
|
112
|
-
rails_env("production")
|
|
113
|
-
|
|
114
|
-
@dummy = Dummy.new
|
|
115
|
-
@dummy.avatar = StringIO.new(".")
|
|
116
|
-
|
|
117
|
-
AWS::S3::S3Object.expects(:url_for).with("avatars/stringio.txt", "prod_bucket", { :expires_in => 3600 })
|
|
118
|
-
|
|
119
|
-
@dummy.avatar.expiring_url
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
should "should succeed" do
|
|
123
|
-
assert true
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
99
|
|
|
127
100
|
context "Parsing S3 credentials with a bucket in them" do
|
|
128
101
|
setup do
|
data/test/thumbnail_test.rb
CHANGED
|
@@ -200,7 +200,7 @@ class ThumbnailTest < Test::Unit::TestCase
|
|
|
200
200
|
teardown { @file.close }
|
|
201
201
|
|
|
202
202
|
should "start with two pages with dimensions 612x792" do
|
|
203
|
-
cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
|
|
203
|
+
cmd = %Q[identify -format "%wx%h" "#{@file.path}"]
|
|
204
204
|
assert_equal "612x792"*2, `#{cmd}`.chomp
|
|
205
205
|
end
|
|
206
206
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bteitelb-paperclip
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.3.1.
|
|
4
|
+
version: 2.3.1.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jon Yurek
|
|
@@ -100,7 +100,6 @@ files:
|
|
|
100
100
|
- lib/paperclip/matchers.rb
|
|
101
101
|
- lib/paperclip/processor.rb
|
|
102
102
|
- lib/paperclip/storage.rb
|
|
103
|
-
- lib/paperclip/style.rb
|
|
104
103
|
- lib/paperclip/thumbnail.rb
|
|
105
104
|
- lib/paperclip/upfile.rb
|
|
106
105
|
- lib/paperclip.rb
|
data/lib/paperclip/style.rb
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
module Paperclip
|
|
3
|
-
# The Style class holds the definition of a thumbnail style, applying
|
|
4
|
-
# whatever processing is required to normalize the definition and delaying
|
|
5
|
-
# the evaluation of block parameters until useful context is available.
|
|
6
|
-
|
|
7
|
-
class Style
|
|
8
|
-
|
|
9
|
-
attr_reader :name, :attachment, :format
|
|
10
|
-
|
|
11
|
-
# Creates a Style object. +name+ is the name of the attachment,
|
|
12
|
-
# +definition+ is the style definition from has_attached_file, which
|
|
13
|
-
# can be string, array or hash
|
|
14
|
-
def initialize name, definition, attachment
|
|
15
|
-
@name = name
|
|
16
|
-
@attachment = attachment
|
|
17
|
-
if definition.is_a? Hash
|
|
18
|
-
@geometry = definition.delete(:geometry)
|
|
19
|
-
@format = definition.delete(:format)
|
|
20
|
-
@processors = definition.delete(:processors)
|
|
21
|
-
@other_args = definition
|
|
22
|
-
else
|
|
23
|
-
@geometry, @format = [definition, nil].flatten[0..1]
|
|
24
|
-
@other_args = {}
|
|
25
|
-
end
|
|
26
|
-
@format = nil if @format.blank?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# retrieves from the attachment the processors defined in the has_attached_file call
|
|
30
|
-
# (which method (in the attachment) will call any supplied procs)
|
|
31
|
-
# There is an important change of interface here: a style rule can set its own processors
|
|
32
|
-
# by default we behave as before, though.
|
|
33
|
-
def processors
|
|
34
|
-
@processors || attachment.processors
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# retrieves from the attachment the whiny setting
|
|
38
|
-
def whiny
|
|
39
|
-
attachment.whiny
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# returns true if we're inclined to grumble
|
|
43
|
-
def whiny?
|
|
44
|
-
!!whiny
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def convert_options
|
|
48
|
-
attachment.send(:extra_options_for, name)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# returns the geometry string for this style
|
|
52
|
-
# if a proc has been supplied, we call it here
|
|
53
|
-
def geometry
|
|
54
|
-
@geometry.respond_to?(:call) ? @geometry.call(attachment.instance) : @geometry
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Supplies the hash of options that processors expect to receive as their second argument
|
|
58
|
-
# Arguments other than the standard geometry, format etc are just passed through from
|
|
59
|
-
# initialization and any procs are called here, just before post-processing.
|
|
60
|
-
def processor_options
|
|
61
|
-
args = {}
|
|
62
|
-
@other_args.each do |k,v|
|
|
63
|
-
args[k] = v.respond_to?(:call) ? v.call(attachment) : v
|
|
64
|
-
end
|
|
65
|
-
[:processors, :geometry, :format, :whiny, :convert_options].each do |k|
|
|
66
|
-
(arg = send(k)) && args[k] = arg
|
|
67
|
-
end
|
|
68
|
-
args
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Supports getting and setting style properties with hash notation to ensure backwards-compatibility
|
|
72
|
-
# eg. @attachment.styles[:large][:geometry]@ will still work
|
|
73
|
-
def [](key)
|
|
74
|
-
if [:name, :convert_options, :whiny, :processors, :geometry, :format].include?(key)
|
|
75
|
-
send(key)
|
|
76
|
-
elsif defined? @other_args[key]
|
|
77
|
-
@other_args[key]
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def []=(key, value)
|
|
82
|
-
if [:name, :convert_options, :whiny, :processors, :geometry, :format].include?(key)
|
|
83
|
-
send("#{key}=".intern, value)
|
|
84
|
-
else
|
|
85
|
-
@other_args[key] = value
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
end
|
|
90
|
-
end
|