bteitelb-paperclip 2.3.1.11 → 2.3.1.12

Sign up to get free protection for your applications and to get access to all the features.
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