bteitelb-paperclip 2.3.1.11 → 2.3.1.12

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 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 'thoughtbot-shoulda'
79
- s.add_development_dependency 'jferris-mocha', '= 0.9.5.0.1241126838'
78
+ s.add_development_dependency '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,6 +34,7 @@ require 'paperclip/processor'
34
34
  require 'paperclip/thumbnail'
35
35
  require 'paperclip/storage'
36
36
  require 'paperclip/interpolations'
37
+ require 'paperclip/style'
37
38
  require 'paperclip/attachment'
38
39
  if defined? RAILS_ROOT
39
40
  Dir.glob(File.join(File.expand_path(RAILS_ROOT), "lib", "paperclip_processors", "*.rb")).each do |processor|
@@ -239,7 +240,7 @@ module Paperclip
239
240
 
240
241
  validates_each(name) do |record, attr, value|
241
242
  attachment = record.attachment_for(name)
242
- attachment.send(:flush_errors) unless attachment.valid?
243
+ attachment.send(:flush_errors)
243
244
  end
244
245
  end
245
246
 
@@ -257,13 +258,13 @@ module Paperclip
257
258
  max = options[:less_than] || (options[:in] && options[:in].last) || (1.0/0)
258
259
  range = (min..max)
259
260
  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)
260
262
 
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]}]
263
+ validates_inclusion_of :"#{name}_file_size",
264
+ :in => range,
265
+ :message => message,
266
+ :if => options[:if],
267
+ :unless => options[:unless]
267
268
  end
268
269
 
269
270
  # Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
@@ -281,9 +282,10 @@ module Paperclip
281
282
  # * +unless+: Same as +if+ but validates if lambda or method returns false.
282
283
  def validates_attachment_presence name, options = {}
283
284
  message = options[:message] || "must be set."
284
- attachment_definitions[name][:validations] << [:presence, {:message => message,
285
- :if => options[:if],
286
- :unless => options[:unless]}]
285
+ validates_presence_of :"#{name}_file_name",
286
+ :message => message,
287
+ :if => options[:if],
288
+ :unless => options[:unless]
287
289
  end
288
290
 
289
291
  # Places ActiveRecord-style validations on the content type of the file
@@ -303,10 +305,12 @@ module Paperclip
303
305
  # model, content_type validation will work _ONLY upon assignment_ and
304
306
  # re-validation after the instance has been reloaded will always succeed.
305
307
  def validates_attachment_content_type name, options = {}
306
- attachment_definitions[name][:validations] << [:content_type, {:content_type => options[:content_type],
307
- :message => options[:message],
308
- :if => options[:if],
309
- :unless => options[:unless]}]
308
+ types = [options.delete(:content_type)].flatten
309
+ validates_each(:"#{name}_content_type", options) do |record, attr, value|
310
+ unless types.any?{|t| t === value }
311
+ record.errors.add(:"#{name}_content_type", :inclusion, :default => options[:message], :value => value)
312
+ end
313
+ end
310
314
  end
311
315
 
312
316
  # Returns the attachment definitions defined by each call to
@@ -9,18 +9,19 @@ module Paperclip
9
9
 
10
10
  def self.default_options
11
11
  @default_options ||= {
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]
12
+ :url => "/system/:attachment/:id/:style/:filename",
13
+ :path => ":rails_root/public:url",
14
+ :styles => {},
15
+ :processors => [:thumbnail],
16
+ :convert_options => {},
17
+ :default_url => "/:attachment/:style/missing.png",
18
+ :default_style => :original,
19
+ :storage => :filesystem,
20
+ :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails]
20
21
  }
21
22
  end
22
23
 
23
- attr_reader :name, :instance, :styles, :default_style, :convert_options, :queued_for_write, :options
24
+ attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny, :options
24
25
 
25
26
  # Creates an Attachment object. +name+ is the name of the attachment,
26
27
  # +instance+ is the ActiveRecord object instance it's attached to, and
@@ -36,14 +37,13 @@ module Paperclip
36
37
  @path = options[:path]
37
38
  @path = @path.call(self) if @path.is_a?(Proc)
38
39
  @styles = options[:styles]
39
- @styles = @styles.call(self) if @styles.is_a?(Proc)
40
+ @normalized_styles = nil
40
41
  @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] || [:thumbnail]
45
+ @convert_options = options[:convert_options]
46
+ @processors = options[:processors]
47
47
  @options = options
48
48
  @queued_for_delete = []
49
49
  @queued_for_write = {}
@@ -52,18 +52,29 @@ module Paperclip
52
52
  @validation_errors = nil
53
53
  @dirty = false
54
54
 
55
- normalize_style_definition
56
55
  initialize_storage
57
56
  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
58
71
 
59
72
  # What gets called when you call instance.attachment = File. It clears
60
- # errors, assigns attributes, processes the file, and runs validations. It
73
+ # errors, assigns attributes, and processes the file. It
61
74
  # also queues up the previous file for deletion, to be flushed away on
62
75
  # #save of its host. In addition to form uploads, you can also assign
63
76
  # another Paperclip attachment:
64
77
  # 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.
67
78
  def assign uploaded_file
68
79
  ensure_required_accessors!
69
80
 
@@ -93,7 +104,7 @@ module Paperclip
93
104
 
94
105
  @dirty = true
95
106
 
96
- post_process if valid?
107
+ post_process
97
108
 
98
109
  # Reset the file size if the original file was reprocessed.
99
110
  instance_write(:file_size, @queued_for_write[:original].size.to_i)
@@ -115,7 +126,6 @@ module Paperclip
115
126
  end
116
127
  ensure
117
128
  uploaded_file.close if close_uploaded_file
118
- validate
119
129
  end
120
130
 
121
131
  # Returns the public URL of the attachment, with a given style. Note that
@@ -125,8 +135,8 @@ module Paperclip
125
135
  # security, however, for performance reasons. set
126
136
  # include_updated_timestamp to false if you want to stop the attachment
127
137
  # update time appended to the url
128
- def url style = default_style, include_updated_timestamp = true
129
- url = original_filename.nil? ? interpolate(@default_url, style) : interpolate(@url, style)
138
+ def url style_name = default_style, include_updated_timestamp = true
139
+ url = original_filename.nil? ? interpolate(@default_url, style_name) : interpolate(@url, style_name)
130
140
  include_updated_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url
131
141
  end
132
142
 
@@ -134,19 +144,13 @@ module Paperclip
134
144
  # file is stored in the filesystem the path refers to the path of the file
135
145
  # on disk. If the file is stored in S3, the path is the "key" part of the
136
146
  # URL, and the :bucket option refers to the S3 bucket.
137
- def path style = default_style
138
- original_filename.nil? ? nil : interpolate(@path, style)
147
+ def path style_name = default_style
148
+ original_filename.nil? ? nil : interpolate(@path, style_name)
139
149
  end
140
150
 
141
151
  # Alias to +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?
152
+ def to_s style_name = nil
153
+ url(style_name)
150
154
  end
151
155
 
152
156
  # Returns an array containing the errors on this attachment.
@@ -162,15 +166,10 @@ module Paperclip
162
166
  # Saves the file, if there are no errors. If there are, it flushes them to
163
167
  # the instance's errors and returns false, cancelling the save.
164
168
  def save
165
- if valid?
166
- flush_deletes
167
- flush_writes
168
- @dirty = false
169
- true
170
- else
171
- flush_errors
172
- false
173
- end
169
+ flush_deletes
170
+ flush_writes
171
+ @dirty = false
172
+ true
174
173
  end
175
174
 
176
175
  # Clears out the attachment. Has the same effect as previously assigning
@@ -179,7 +178,6 @@ module Paperclip
179
178
  def clear
180
179
  queue_existing_for_delete
181
180
  @errors = {}
182
- @validation_errors = nil
183
181
  end
184
182
 
185
183
  # Destroys the attachment. Has the same effect as previously assigning
@@ -271,15 +269,6 @@ module Paperclip
271
269
  # Determines whether or not the attachment is an image based on the content_type
272
270
  def image?
273
271
  !content_type.nil? and !!content_type.match(%r{\Aimage/})
274
-
275
- # Fix content type when it's application/octet-stream
276
- if content_type.to_s.strip == 'application/octet-stream'
277
- mime_type = MIME::Types.type_for(uploaded_file.original_filename.strip).to_s
278
- end
279
- instance_write(:content_type, uploaded_file.content_type.to_s.strip)
280
- instance_write(:file_size, uploaded_file.size.to_i)
281
- instance_write(:updated_at, Time.now)
282
-
283
272
  end
284
273
 
285
274
  # Writes the attachment-specific attribute on the instance. For example,
@@ -320,82 +309,6 @@ module Paperclip
320
309
  file.nil? || (file.respond_to?(:original_filename) && file.respond_to?(:content_type))
321
310
  end
322
311
 
323
- def validate #:nodoc:
324
- unless @validation_errors
325
- @validation_errors = @validations.inject({}) do |errors, validation|
326
- name, options = validation
327
- errors[name] = send(:"validate_#{name}", options) if allow_validation?(options)
328
- errors
329
- end
330
- @validation_errors.reject!{|k,v| v == nil }
331
- @errors.merge!(@validation_errors)
332
- end
333
- @validation_errors
334
- end
335
-
336
- def allow_validation? options #:nodoc:
337
- (options[:if].nil? || check_guard(options[:if])) && (options[:unless].nil? || !check_guard(options[:unless]))
338
- end
339
-
340
- def check_guard guard #:nodoc:
341
- if guard.respond_to? :call
342
- guard.call(instance)
343
- elsif ! guard.blank?
344
- instance.send(guard.to_s)
345
- end
346
- end
347
-
348
- def validate_size options #:nodoc:
349
- if file? && !options[:range].include?(size.to_i)
350
- options[:message].gsub(/:min/, options[:min].to_s).gsub(/:max/, options[:max].to_s)
351
- end
352
- end
353
-
354
- def validate_presence options #:nodoc:
355
- options[:message] unless file?
356
- end
357
-
358
- def validate_content_type options #:nodoc:
359
- valid_types = [options[:content_type]].flatten
360
- unless original_filename.blank?
361
- unless valid_types.blank?
362
- content_type = instance_read(:content_type)
363
- unless valid_types.any?{|t| content_type.nil? || t === content_type }
364
- options[:message] || "is not one of the allowed file types."
365
- end
366
- end
367
- end
368
- end
369
-
370
- def normalize_style_definition #:nodoc:
371
- @styles.each do |name, args|
372
- unless args.is_a? Hash
373
- dimensions, format = [args, nil].flatten[0..1]
374
- format = nil if format.blank?
375
- @styles[name] = {
376
- :processors => @processors,
377
- :geometry => dimensions,
378
- :format => format,
379
- :whiny => @whiny,
380
- :convert_options => extra_options_for(name)
381
- }
382
- else
383
- @styles[name] = {
384
- :processors => @processors,
385
- :whiny => @whiny,
386
- :convert_options => extra_options_for(name)
387
- }.merge(@styles[name])
388
- end
389
- end
390
- end
391
-
392
- def solidify_style_definitions #:nodoc:
393
- @styles.each do |name, args|
394
- @styles[name][:geometry] = @styles[name][:geometry].call(instance) if @styles[name][:geometry].respond_to?(:call)
395
- @styles[name][:processors] = @styles[name][:processors].call(instance) if @styles[name][:processors].respond_to?(:call)
396
- end
397
- end
398
-
399
312
  def initialize_storage #:nodoc:
400
313
  @storage_module = Paperclip::Storage.const_get(@storage.to_s.capitalize)
401
314
  self.extend(@storage_module)
@@ -412,7 +325,6 @@ module Paperclip
412
325
 
413
326
  def post_process #:nodoc:
414
327
  return if @queued_for_write[:original].nil?
415
- solidify_style_definitions
416
328
  return if fire_events(:before)
417
329
  post_process_styles
418
330
  return if fire_events(:after)
@@ -428,11 +340,11 @@ module Paperclip
428
340
  end
429
341
 
430
342
  def post_process_styles #:nodoc:
431
- @styles.each do |name, args|
343
+ styles.each do |name, style|
432
344
  begin
433
- raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
434
- @queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
435
- Paperclip.processor(processor).make(file, args, self)
345
+ raise RuntimeError.new("Style #{name} has no processors defined.") if style.processors.blank?
346
+ @queued_for_write[name] = style.processors.inject(@queued_for_write[:original]) do |file, processor|
347
+ Paperclip.processor(processor).make(file, style.processor_options, self)
436
348
  end
437
349
  rescue PaperclipError => e
438
350
  log("An error was received while processing: #{e.inspect}")
@@ -441,8 +353,8 @@ module Paperclip
441
353
  end
442
354
  end
443
355
 
444
- def interpolate pattern, style = default_style #:nodoc:
445
- Paperclip::Interpolations.interpolate(pattern, self, style)
356
+ def interpolate pattern, style_name = default_style #:nodoc:
357
+ Paperclip::Interpolations.interpolate(pattern, self, style_name)
446
358
  end
447
359
 
448
360
  def mime_type
@@ -469,7 +381,7 @@ module Paperclip
469
381
 
470
382
  def queue_existing_for_delete #:nodoc:
471
383
  return unless file?
472
- @queued_for_delete += [:original, *@styles.keys].uniq.map do |style|
384
+ @queued_for_delete += [:original, *styles.keys].uniq.map do |style|
473
385
  path(style) if exists?(style)
474
386
  end.compact
475
387
  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, style
38
- "#{basename(attachment, style)}.#{extension(attachment, style)}"
37
+ def filename attachment, style_name
38
+ "#{basename(attachment, style_name)}.#{extension(attachment, style_name)}"
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, style
44
+ def url attachment, style_name
45
45
  raise InfiniteInterpolationError if attachment.options[:url].include?(":url")
46
- attachment.url(style, false)
46
+ attachment.url(style_name, false)
47
47
  end
48
48
 
49
49
  # Returns the timestamp as defined by the <attachment>_updated_at field
50
- def timestamp attachment, style
50
+ def timestamp attachment, style_name
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, style
55
+ def rails_root attachment, style_name
56
56
  RAILS_ROOT
57
57
  end
58
58
 
59
59
  # Returns the RAILS_ENV constant.
60
- def rails_env attachment, style
60
+ def rails_env attachment, style_name
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, style = nil
69
- return super() if attachment.nil? && style.nil?
68
+ def class attachment = nil, style_name = nil
69
+ return super() if attachment.nil? && style_name.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, style
74
+ def basename attachment, style_name
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, style
82
- ((style = attachment.styles[style]) && style[:format]) ||
81
+ def extension attachment, style_name
82
+ ((style = attachment.styles[style_name]) && 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, style
87
+ def id attachment, style_name
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, style
93
+ def id_partition attachment, style_name
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, style
99
+ def attachment attachment, style_name
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, style
105
- style || attachment.default_style
104
+ def style attachment, style_name
105
+ style_name || attachment.default_style
106
106
  end
107
107
  end
108
108
  end
@@ -4,7 +4,8 @@ module IOStream
4
4
 
5
5
  # Returns a Tempfile containing the contents of the readable object.
6
6
  def to_tempfile
7
- tempfile = Tempfile.new("stream")
7
+ name = respond_to?(:original_filename) ? original_filename : (respond_to?(:path) ? path : "stream")
8
+ tempfile = Paperclip::Tempfile.new(File.basename(name))
8
9
  tempfile.binmode
9
10
  self.stream_to(tempfile)
10
11
  end
@@ -46,9 +46,8 @@ module Paperclip
46
46
  types.all? do |type|
47
47
  file = StringIO.new(".")
48
48
  file.content_type = type
49
- attachment = @subject.new.attachment_for(@attachment_name)
50
- attachment.assign(file)
51
- attachment.errors[:content_type].nil?
49
+ (subject = @subject.new).attachment_for(@attachment_name).assign(file)
50
+ subject.valid? && subject.errors.on(:"#{@attachment_name}_content_type").blank?
52
51
  end
53
52
  end
54
53
 
@@ -30,16 +30,16 @@ module Paperclip
30
30
  protected
31
31
 
32
32
  def error_when_not_valid?
33
- @attachment = @subject.new.send(@attachment_name)
34
- @attachment.assign(nil)
35
- not @attachment.errors[:presence].nil?
33
+ (subject = @subject.new).send(@attachment_name).assign(nil)
34
+ subject.valid?
35
+ not subject.errors.on(:"#{@attachment_name}_file_name").blank?
36
36
  end
37
37
 
38
38
  def no_error_when_valid?
39
39
  @file = StringIO.new(".")
40
- @attachment = @subject.new.send(@attachment_name)
41
- @attachment.assign(@file)
42
- @attachment.errors[:presence].nil?
40
+ (subject = @subject.new).send(@attachment_name).assign(@file)
41
+ subject.valid?
42
+ subject.errors.on(:"#{@attachment_name}_file_name").blank?
43
43
  end
44
44
  end
45
45
  end
@@ -54,9 +54,11 @@ 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
- attachment = @subject.new.attachment_for(@attachment_name)
58
- attachment.assign(file)
59
- attachment.errors[:size].nil?
57
+ override_method(file, :to_tempfile){ file }
58
+
59
+ (subject = @subject.new).send(@attachment_name).assign(file)
60
+ subject.valid?
61
+ subject.errors.on(:"#{@attachment_name}_file_size").blank?
60
62
  end
61
63
 
62
64
  def lower_than_low?
@@ -20,9 +20,9 @@ module Paperclip
20
20
  def self.extended base
21
21
  end
22
22
 
23
- def exists?(style = default_style)
23
+ def exists?(style_name = default_style)
24
24
  if original_filename
25
- File.exist?(path(style))
25
+ File.exist?(path(style_name))
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 style = default_style
34
- @queued_for_write[style] || (File.new(path(style), 'rb') if exists?(style))
33
+ def to_file style_name = default_style
34
+ @queued_for_write[style_name] || (File.new(path(style_name), 'rb') if exists?(style_name))
35
35
  end
36
36
 
37
37
  def flush_writes #:nodoc:
38
- @queued_for_write.each do |style, file|
38
+ @queued_for_write.each do |style_name, file|
39
39
  file.close
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))
40
+ FileUtils.mkdir_p(File.dirname(path(style_name)))
41
+ log("saving #{path(style_name)}")
42
+ FileUtils.mv(file.path, path(style_name))
43
+ FileUtils.chmod(0644, path(style_name))
44
44
  end
45
45
  @queued_for_write = {}
46
46
  end
@@ -159,6 +159,10 @@ 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
162
166
 
163
167
  def bucket_name
164
168
  @bucket
@@ -12,6 +12,7 @@ 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
+
15
16
  geometry = options[:geometry]
16
17
  @file = file
17
18
  @crop = geometry[-1,1] == '#'
@@ -24,6 +25,7 @@ module Paperclip
24
25
 
25
26
  @current_format = File.extname(@file.path)
26
27
  @basename = File.basename(@file.path, @current_format)
28
+
27
29
  end
28
30
 
29
31
  # Returns true if the +target_geometry+ is meant to crop.
@@ -14,18 +14,6 @@ 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
-
29
17
  context "Attachment default_options" do
30
18
  setup do
31
19
  rebuild_model
@@ -133,7 +121,7 @@ class AttachmentTest < Test::Unit::TestCase
133
121
  :styles => { :default => ["100x100", :png] },
134
122
  :default_style => :default
135
123
  @file = StringIO.new("...")
136
- @file.expects(:original_filename).returns("file.jpg")
124
+ @file.stubs(:original_filename).returns("file.jpg")
137
125
  end
138
126
  should "return the right extension for the path" do
139
127
  @attachment.assign(@file)
@@ -162,11 +150,6 @@ class AttachmentTest < Test::Unit::TestCase
162
150
  should "report the correct options when sent #extra_options_for(:large)" do
163
151
  assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
164
152
  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
170
153
  end
171
154
 
172
155
  context "An attachment with :convert_options that is a proc" do
@@ -194,11 +177,6 @@ class AttachmentTest < Test::Unit::TestCase
194
177
  should "report the correct options when sent #extra_options_for(:large)" do
195
178
  assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
196
179
  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
202
180
  end
203
181
 
204
182
  context "An attachment with :path that is a proc" do
@@ -267,10 +245,6 @@ class AttachmentTest < Test::Unit::TestCase
267
245
  @attachment = Dummy.new.avatar
268
246
  end
269
247
 
270
- should "not run the procs immediately" do
271
- assert_kind_of Proc, @attachment.styles[:normal][:geometry]
272
- end
273
-
274
248
  context "when assigned" do
275
249
  setup do
276
250
  @file = StringIO.new(".")
@@ -307,10 +281,6 @@ class AttachmentTest < Test::Unit::TestCase
307
281
  @attachment = Dummy.new.avatar
308
282
  end
309
283
 
310
- should "not run the proc immediately" do
311
- assert_kind_of Proc, @attachment.styles[:normal][:processors]
312
- end
313
-
314
284
  context "when assigned" do
315
285
  setup do
316
286
  @attachment.assign(StringIO.new("."))
@@ -354,19 +324,22 @@ class AttachmentTest < Test::Unit::TestCase
354
324
  setup { @dummy.avatar = @file }
355
325
 
356
326
  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
357
332
  expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => true, :convert_options => ""})
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)
333
+ Paperclip::Thumbnail.expects(:make).with(anything, expected_params, anything).returns(@file)
360
334
  end
361
335
 
362
336
  before_should "call #make with attachment passed as third argument" do
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)
337
+ Paperclip::Test.expects(:make).with(anything, anything, @dummy.avatar).returns(@file)
365
338
  end
366
339
  end
367
340
  end
368
341
 
369
- context "An attachment with no processors defined" do
342
+ context "An attachment with styles but no processors defined" do
370
343
  setup do
371
344
  rebuild_model :processors => [], :styles => {:something => 1}
372
345
  @dummy = Dummy.new
@@ -377,6 +350,17 @@ class AttachmentTest < Test::Unit::TestCase
377
350
  end
378
351
  end
379
352
 
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
+
380
364
  context "Assigning an attachment with post_process hooks" do
381
365
  setup do
382
366
  rebuild_model :styles => { :something => "100x100#" }
@@ -478,8 +462,6 @@ class AttachmentTest < Test::Unit::TestCase
478
462
  @attachment.expects(:valid_assignment?).with(@not_file).returns(true)
479
463
  @attachment.expects(:queue_existing_for_delete)
480
464
  @attachment.expects(:post_process)
481
- @attachment.expects(:valid?).returns(true)
482
- @attachment.expects(:validate)
483
465
  @dummy.avatar = @not_file
484
466
  end
485
467
 
@@ -498,6 +480,7 @@ class AttachmentTest < Test::Unit::TestCase
498
480
  FileUtils.rm_rf("tmp")
499
481
  rebuild_model
500
482
  @instance = Dummy.new
483
+ @instance.stubs(:id).returns 123
501
484
  @attachment = Paperclip::Attachment.new(:avatar, @instance)
502
485
  @file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
503
486
  end
@@ -606,6 +589,7 @@ class AttachmentTest < Test::Unit::TestCase
606
589
  should "commit the files to disk" do
607
590
  [:large, :medium, :small].each do |style|
608
591
  io = @attachment.to_file(style)
592
+ # p "in commit to disk test, io is #{io.inspect} and @instance.id is #{@instance.id}"
609
593
  assert File.exists?(io)
610
594
  assert ! io.is_a?(::Tempfile)
611
595
  io.close
data/test/helper.rb CHANGED
@@ -3,7 +3,7 @@ require 'test/unit'
3
3
  require 'shoulda'
4
4
  require 'tempfile'
5
5
 
6
- gem 'jferris-mocha', '0.9.5.0.1241126838'
6
+ gem 'jferris-mocha'
7
7
  require 'mocha'
8
8
 
9
9
  gem 'sqlite3-ruby'
@@ -58,8 +58,15 @@ class IOStreamTest < Test::Unit::TestCase
58
58
  assert @tempfile = @file.to_tempfile
59
59
  end
60
60
 
61
- should "convert it to a Tempfile" do
62
- assert @tempfile.is_a?(Tempfile)
61
+ should "convert it to a Paperclip Tempfile" do
62
+ assert @tempfile.is_a?(Paperclip::Tempfile)
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)
63
70
  end
64
71
 
65
72
  should "have the Tempfile contain the same data as the file" do
@@ -5,6 +5,7 @@ class ValidateAttachmentContentTypeMatcherTest < Test::Unit::TestCase
5
5
  setup do
6
6
  reset_table("dummies") do |d|
7
7
  d.string :avatar_file_name
8
+ d.string :avatar_content_type
8
9
  end
9
10
  @dummy_class = reset_class "Dummy"
10
11
  @dummy_class.has_attached_file :avatar
@@ -3,7 +3,9 @@ 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"){|d| d.string :avatar_file_name }
6
+ reset_table("dummies") do |d|
7
+ d.string :avatar_file_name
8
+ end
7
9
  @dummy_class = reset_class "Dummy"
8
10
  @dummy_class.has_attached_file :avatar
9
11
  @matcher = self.class.validate_attachment_presence(:avatar)
@@ -5,6 +5,7 @@ class ValidateAttachmentSizeMatcherTest < Test::Unit::TestCase
5
5
  setup do
6
6
  reset_table("dummies") do |d|
7
7
  d.string :avatar_file_name
8
+ d.integer :avatar_file_size
8
9
  end
9
10
  @dummy_class = reset_class "Dummy"
10
11
  @dummy_class.has_attached_file :avatar
@@ -185,45 +185,23 @@ 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
209
188
  end
210
189
 
211
190
  context "a validation with an if guard clause" do
212
191
  setup do
213
192
  Dummy.send(:"validates_attachment_presence", :avatar, :if => lambda{|i| i.foo })
214
193
  @dummy = Dummy.new
194
+ @dummy.stubs(:avatar_file_name).returns(nil)
215
195
  end
216
196
 
217
197
  should "attempt validation if the guard returns true" do
218
198
  @dummy.expects(:foo).returns(true)
219
- @dummy.avatar.expects(:validate_presence).returns(nil)
220
- @dummy.valid?
199
+ assert ! @dummy.valid?
221
200
  end
222
201
 
223
202
  should "not attempt validation if the guard returns false" do
224
203
  @dummy.expects(:foo).returns(false)
225
- @dummy.avatar.expects(:validate_presence).never
226
- @dummy.valid?
204
+ assert @dummy.valid?
227
205
  end
228
206
  end
229
207
 
@@ -231,18 +209,17 @@ class PaperclipTest < Test::Unit::TestCase
231
209
  setup do
232
210
  Dummy.send(:"validates_attachment_presence", :avatar, :unless => lambda{|i| i.foo })
233
211
  @dummy = Dummy.new
212
+ @dummy.stubs(:avatar_file_name).returns(nil)
234
213
  end
235
214
 
236
215
  should "attempt validation if the guard returns true" do
237
216
  @dummy.expects(:foo).returns(false)
238
- @dummy.avatar.expects(:validate_presence).returns(nil)
239
- @dummy.valid?
217
+ assert ! @dummy.valid?
240
218
  end
241
219
 
242
220
  should "not attempt validation if the guard returns false" do
243
221
  @dummy.expects(:foo).returns(true)
244
- @dummy.avatar.expects(:validate_presence).never
245
- @dummy.valid?
222
+ assert @dummy.valid?
246
223
  end
247
224
  end
248
225
 
@@ -259,11 +236,11 @@ class PaperclipTest < Test::Unit::TestCase
259
236
  end
260
237
  if validation == :presence
261
238
  should "have an error on the attachment" do
262
- assert @dummy.errors.on(:avatar)
239
+ assert @dummy.errors.on(:avatar_file_name)
263
240
  end
264
241
  else
265
242
  should "not have an error on the attachment" do
266
- assert_nil @dummy.errors.on(:avatar)
243
+ assert_nil @dummy.errors.on(:avatar_file_name), @dummy.errors.full_messages.join(", ")
267
244
  end
268
245
  end
269
246
  end
@@ -273,10 +250,7 @@ class PaperclipTest < Test::Unit::TestCase
273
250
  @dummy.valid?
274
251
  end
275
252
  should "not have an error when assigned a valid file" do
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)
253
+ assert_equal 0, @dummy.errors.length, @dummy.errors.full_messages.join(", ")
280
254
  end
281
255
  end
282
256
  context "and assigned an invalid file" do
@@ -285,17 +259,14 @@ class PaperclipTest < Test::Unit::TestCase
285
259
  @dummy.valid?
286
260
  end
287
261
  should "have an error when assigned a valid file" do
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)
262
+ assert @dummy.errors.length > 0
292
263
  end
293
264
  end
294
265
  end
295
266
  end
296
267
 
297
268
  [[:presence, {}, "5k.png", nil],
298
- [:size, {:in => 1..10240}, nil, "12k.png"],
269
+ [:size, {:in => 1..10240}, "5k.png", "12k.png"],
299
270
  [:size, {:less_than => 10240}, "5k.png", "12k.png"],
300
271
  [:size, {:greater_than => 8096}, "12k.png", "5k.png"],
301
272
  [:content_type, {:content_type => "image/png"}, "5k.png", "text.txt"],
@@ -318,7 +289,7 @@ class PaperclipTest < Test::Unit::TestCase
318
289
  end
319
290
 
320
291
  should "have a file size min/max error message" do
321
- assert_match /between 0 and 10240 bytes/, @dummy.errors.on(:avatar)
292
+ assert_match %r/between 0 and 10240 bytes/, @dummy.errors.on(:avatar_file_size)
322
293
  end
323
294
  end
324
295
  end
data/test/storage_test.rb CHANGED
@@ -96,6 +96,33 @@ 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
99
126
 
100
127
  context "Parsing S3 credentials with a bucket in them" do
101
128
  setup do
@@ -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.11
4
+ version: 2.3.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Yurek