paperclip 2.4.5 → 2.5.0

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

Potentially problematic release.


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

Files changed (63) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +13 -0
  3. data/Appraisals +14 -0
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +5 -0
  6. data/NEWS +23 -0
  7. data/README.md +72 -42
  8. data/Rakefile +1 -46
  9. data/cucumber/paperclip_steps.rb +6 -0
  10. data/features/basic_integration.feature +46 -0
  11. data/features/rake_tasks.feature +63 -0
  12. data/features/step_definitions/attachment_steps.rb +65 -0
  13. data/features/step_definitions/html_steps.rb +15 -0
  14. data/features/step_definitions/rails_steps.rb +182 -0
  15. data/features/step_definitions/s3_steps.rb +14 -0
  16. data/features/step_definitions/web_steps.rb +209 -0
  17. data/features/support/env.rb +8 -0
  18. data/features/support/fakeweb.rb +3 -0
  19. data/features/support/fixtures/.boot_config.rb.swo +0 -0
  20. data/features/support/fixtures/boot_config.txt +15 -0
  21. data/features/support/fixtures/gemfile.txt +5 -0
  22. data/features/support/fixtures/preinitializer.txt +20 -0
  23. data/features/support/paths.rb +28 -0
  24. data/features/support/rails.rb +46 -0
  25. data/features/support/selectors.rb +19 -0
  26. data/gemfiles/rails2.gemfile +9 -0
  27. data/gemfiles/rails3.gemfile +9 -0
  28. data/gemfiles/rails3_1.gemfile +9 -0
  29. data/lib/paperclip.rb +26 -19
  30. data/lib/paperclip/attachment.rb +123 -109
  31. data/lib/paperclip/interpolations.rb +7 -4
  32. data/lib/paperclip/matchers.rb +33 -2
  33. data/lib/paperclip/missing_attachment_styles.rb +1 -1
  34. data/lib/paperclip/railtie.rb +5 -0
  35. data/lib/paperclip/schema.rb +39 -0
  36. data/lib/paperclip/storage/fog.rb +21 -10
  37. data/lib/paperclip/storage/s3.rb +107 -40
  38. data/lib/paperclip/style.rb +13 -5
  39. data/lib/paperclip/url_generator.rb +64 -0
  40. data/lib/paperclip/version.rb +1 -1
  41. data/lib/tasks/paperclip.rake +1 -1
  42. data/paperclip.gemspec +41 -0
  43. data/test/.gitignore +1 -0
  44. data/test/attachment_test.rb +155 -168
  45. data/test/fixtures/question?mark.png +0 -0
  46. data/test/helper.rb +24 -1
  47. data/test/interpolations_test.rb +16 -2
  48. data/test/paperclip_missing_attachment_styles_test.rb +16 -0
  49. data/test/paperclip_test.rb +72 -22
  50. data/test/schema_test.rb +98 -0
  51. data/test/storage/filesystem_test.rb +2 -2
  52. data/test/{fog_test.rb → storage/fog_test.rb} +35 -8
  53. data/test/storage/s3_live_test.rb +63 -13
  54. data/test/storage/s3_test.rb +394 -91
  55. data/test/style_test.rb +50 -21
  56. data/test/support/mock_attachment.rb +22 -0
  57. data/test/support/mock_interpolator.rb +24 -0
  58. data/test/support/mock_model.rb +2 -0
  59. data/test/support/mock_url_generator_builder.rb +27 -0
  60. data/test/url_generator_test.rb +187 -0
  61. metadata +307 -125
  62. data/lib/paperclip/options.rb +0 -78
  63. data/test/options_test.rb +0 -75
@@ -18,7 +18,13 @@ module Paperclip
18
18
  @geometry = definition.delete(:geometry)
19
19
  @format = definition.delete(:format)
20
20
  @processors = definition.delete(:processors)
21
+ @convert_options = definition.delete(:convert_options)
22
+ @source_file_options = definition.delete(:source_file_options)
21
23
  @other_args = definition
24
+ elsif definition.is_a? String
25
+ @geometry = definition
26
+ @format = nil
27
+ @other_args = {}
22
28
  else
23
29
  @geometry, @format = [definition, nil].flatten[0..1]
24
30
  @other_args = {}
@@ -32,12 +38,12 @@ module Paperclip
32
38
  # by default we behave as before, though.
33
39
  # if a proc has been supplied, we call it here
34
40
  def processors
35
- @processors.respond_to?(:call) ? @processors.call(attachment.instance) : (@processors || attachment.options.processors)
41
+ @processors.respond_to?(:call) ? @processors.call(attachment.instance) : (@processors || attachment.processors)
36
42
  end
37
43
 
38
44
  # retrieves from the attachment the whiny setting
39
45
  def whiny
40
- attachment.options.whiny
46
+ attachment.whiny
41
47
  end
42
48
 
43
49
  # returns true if we're inclined to grumble
@@ -46,11 +52,13 @@ module Paperclip
46
52
  end
47
53
 
48
54
  def convert_options
49
- attachment.send(:extra_options_for, name)
55
+ @convert_options.respond_to?(:call) ? @convert_options.call(attachment.instance) :
56
+ (@convert_options || attachment.send(:extra_options_for, name))
50
57
  end
51
58
 
52
59
  def source_file_options
53
- attachment.send(:extra_source_file_options_for, name)
60
+ @source_file_options.respond_to?(:call) ? @source_file_options.call(attachment.instance) :
61
+ (@source_file_options || attachment.send(:extra_source_file_options_for, name))
54
62
  end
55
63
 
56
64
  # returns the geometry string for this style
@@ -74,7 +82,7 @@ module Paperclip
74
82
  end
75
83
 
76
84
  # Supports getting and setting style properties with hash notation to ensure backwards-compatibility
77
- # eg. @attachment.options.styles[:large][:geometry]@ will still work
85
+ # eg. @attachment.styles[:large][:geometry]@ will still work
78
86
  def [](key)
79
87
  if [:name, :convert_options, :whiny, :processors, :geometry, :format, :animated, :source_file_options].include?(key)
80
88
  send(key)
@@ -0,0 +1,64 @@
1
+ require 'uri'
2
+
3
+ module Paperclip
4
+ class UrlGenerator
5
+ def initialize(attachment, attachment_options)
6
+ @attachment = attachment
7
+ @attachment_options = attachment_options
8
+ end
9
+
10
+ def for(style_name, options)
11
+ escape_url_as_needed(
12
+ timestamp_as_needed(
13
+ @attachment_options[:interpolator].interpolate(most_appropriate_url, @attachment, style_name),
14
+ options
15
+ ), options)
16
+ end
17
+
18
+ private
19
+
20
+ # This method is all over the place.
21
+ def default_url
22
+ if @attachment_options[:default_url].respond_to?(:call)
23
+ @attachment_options[:default_url].call(@attachment)
24
+ elsif @attachment_options[:default_url].is_a?(Symbol)
25
+ @attachment.instance.send(@attachment_options[:default_url])
26
+ else
27
+ @attachment_options[:default_url]
28
+ end
29
+ end
30
+
31
+ def most_appropriate_url
32
+ if @attachment.original_filename.nil?
33
+ default_url
34
+ else
35
+ @attachment_options[:url]
36
+ end
37
+ end
38
+
39
+ def timestamp_as_needed(url, options)
40
+ if options[:timestamp] && timestamp_possible?
41
+ delimiter_char = url.match(/\?.+=/) ? '&' : '?'
42
+ "#{url}#{delimiter_char}#{@attachment.updated_at.to_s}"
43
+ else
44
+ url
45
+ end
46
+ end
47
+
48
+ def timestamp_possible?
49
+ @attachment.respond_to?(:updated_at) && @attachment.updated_at.present?
50
+ end
51
+
52
+ def escape_url_as_needed(url, options)
53
+ if options[:escape]
54
+ escape_url(url)
55
+ else
56
+ url
57
+ end
58
+ end
59
+
60
+ def escape_url(url)
61
+ (url.respond_to?(:escape) ? url.escape : URI.escape(url)).gsub(/(\/.+)\?(.+\.)/, '\1%3F\2')
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Paperclip
2
- VERSION = "2.4.5" unless defined? Paperclip::VERSION
2
+ VERSION = "2.5.0" unless defined? Paperclip::VERSION
3
3
  end
@@ -47,7 +47,7 @@ namespace :paperclip do
47
47
  Paperclip.each_instance_with_attachment(klass, name) do |instance|
48
48
  if file = instance.send(name).to_file(:original)
49
49
  instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
50
- instance.send("#{name}_content_type=", file.content_type.strip)
50
+ instance.send("#{name}_content_type=", file.content_type.to_s.strip)
51
51
  instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
52
52
  if Rails.version >= "3.0.0"
53
53
  instance.save(:validate => false)
@@ -0,0 +1,41 @@
1
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
2
+ require 'paperclip/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "paperclip"
6
+ s.version = Paperclip::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.author = "Jon Yurek"
9
+ s.email = ["jyurek@thoughtbot.com"]
10
+ s.homepage = "https://github.com/thoughtbot/paperclip"
11
+ s.summary = "File attachments as attributes for ActiveRecord"
12
+ s.description = "Easy upload management for ActiveRecord"
13
+
14
+ s.rubyforge_project = "paperclip"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.requirements << "ImageMagick"
22
+
23
+ s.add_dependency('activerecord', '>= 2.3.0')
24
+ s.add_dependency('activesupport', '>= 2.3.2')
25
+ s.add_dependency('cocaine', '>= 0.0.2')
26
+ s.add_dependency('mime-types')
27
+
28
+ s.add_development_dependency('shoulda')
29
+ s.add_development_dependency('appraisal', '~> 0.4.0')
30
+ s.add_development_dependency('mocha')
31
+ s.add_development_dependency('aws-sdk')
32
+ s.add_development_dependency('sqlite3', '~> 1.3.4')
33
+ s.add_development_dependency('cucumber', '~> 1.1.0')
34
+ s.add_development_dependency('aruba')
35
+ s.add_development_dependency('capybara')
36
+ s.add_development_dependency('bundler')
37
+ s.add_development_dependency('cocaine', '~> 0.2')
38
+ s.add_development_dependency('fog')
39
+ s.add_development_dependency('rake')
40
+ s.add_development_dependency('fakeweb')
41
+ end
@@ -0,0 +1 @@
1
+ debug.log
@@ -1,46 +1,106 @@
1
1
  # encoding: utf-8
2
2
  require './test/helper'
3
+ require 'paperclip/attachment'
3
4
 
4
- class Dummy
5
- # This is a dummy class
6
- end
5
+ class Dummy; end
7
6
 
8
7
  class AttachmentTest < Test::Unit::TestCase
9
- should "return the path based on the url by default" do
10
- @attachment = attachment :url => "/:class/:id/:basename"
11
- @model = @attachment.instance
12
- @model.id = 1234
13
- @model.avatar_file_name = "fake.jpg"
14
- assert_equal "#{Rails.root}/public/fake_models/1234/fake", @attachment.path
8
+
9
+ should "process :original style first" do
10
+ file = File.new(File.join(File.dirname(__FILE__), "fixtures", "50x50.png"), 'rb')
11
+ rebuild_class :styles => { :small => '100x>', :original => '42x42#' }
12
+ dummy = Dummy.new
13
+ dummy.avatar = file
14
+ dummy.save
15
+
16
+ # :small avatar should be 42px wide (processed original), not 50px (preprocessed original)
17
+ assert_equal `identify -format "%w" "#{dummy.avatar.path(:small)}"`.strip, "42"
18
+
19
+ file.close
15
20
  end
16
21
 
17
- should "return the url by interpolating the default_url option when no file assigned" do
18
- @attachment = attachment :default_url => ":class/blegga.png"
19
- @model = @attachment.instance
20
- assert_nil @model.avatar_file_name
21
- assert_equal "fake_models/blegga.png", @attachment.url
22
+ should "handle a boolean second argument to #url" do
23
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
24
+ attachment = Paperclip::Attachment.new(:name, :instance, :url_generator => mock_url_generator_builder)
25
+
26
+ attachment.url(:style_name, true)
27
+ assert mock_url_generator_builder.has_generated_url_with_options?(:timestamp => true, :escape => true)
28
+
29
+ attachment.url(:style_name, false)
30
+ assert mock_url_generator_builder.has_generated_url_with_options?(:timestamp => false, :escape => true)
22
31
  end
23
32
 
24
- should "return the url by executing and interpolating the default_url Proc when no file assigned" do
25
- @attachment = attachment :default_url => lambda { |a| ":class/blegga.png" }
26
- @model = @attachment.instance
27
- assert_nil @model.avatar_file_name
28
- assert_equal "fake_models/blegga.png", @attachment.url
33
+ should "pass the style and options through to the URL generator on #url" do
34
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
35
+ attachment = Paperclip::Attachment.new(:name, :instance, :url_generator => mock_url_generator_builder)
36
+
37
+ attachment.url(:style_name, :options => :values)
38
+ assert mock_url_generator_builder.has_generated_url_with_options?(:options => :values)
29
39
  end
30
40
 
31
- should "return the url by executing and interpolating the default_url Proc with attachment arg when no file assigned" do
32
- @attachment = attachment :default_url => lambda { |a| a.instance.some_method_to_determine_default_url }
33
- @model = @attachment.instance
34
- @model.stubs(:some_method_to_determine_default_url).returns(":class/blegga.png")
35
- assert_nil @model.avatar_file_name
36
- assert_equal "fake_models/blegga.png", @attachment.url
41
+ should "pass default options through when #url is given one argument" do
42
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
43
+ attachment = Paperclip::Attachment.new(:name,
44
+ :instance,
45
+ :url_generator => mock_url_generator_builder,
46
+ :use_timestamp => true)
47
+
48
+ attachment.url(:style_name)
49
+ assert mock_url_generator_builder.has_generated_url_with_options?(:escape => true, :timestamp => true)
50
+ end
51
+
52
+ should "pass default style and options through when #url is given no arguments" do
53
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
54
+ attachment = Paperclip::Attachment.new(:name,
55
+ :instance,
56
+ :default_style => 'default style',
57
+ :url_generator => mock_url_generator_builder,
58
+ :use_timestamp => true)
59
+
60
+ attachment.url
61
+ assert mock_url_generator_builder.has_generated_url_with_options?(:escape => true, :timestamp => true)
62
+ assert mock_url_generator_builder.has_generated_url_with_style_name?('default style')
63
+ end
64
+
65
+ should "pass the option :timestamp => true if :use_timestamp is true and :timestamp is not passed" do
66
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
67
+ attachment = Paperclip::Attachment.new(:name,
68
+ :instance,
69
+ :url_generator => mock_url_generator_builder,
70
+ :use_timestamp => true)
71
+
72
+ attachment.url(:style_name)
73
+ assert mock_url_generator_builder.has_generated_url_with_options?(:escape => true, :timestamp => true)
74
+ end
75
+
76
+ should "pass the option :timestamp => false if :use_timestamp is false and :timestamp is not passed" do
77
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
78
+ attachment = Paperclip::Attachment.new(:name,
79
+ :instance,
80
+ :url_generator => mock_url_generator_builder,
81
+ :use_timestamp => false)
82
+
83
+ attachment.url(:style_name)
84
+ assert mock_url_generator_builder.has_generated_url_with_options?(:escape => true, :timestamp => false)
85
+ end
86
+
87
+ should "not change the :timestamp if :timestamp is passed" do
88
+ mock_url_generator_builder = MockUrlGeneratorBuilder.new
89
+ attachment = Paperclip::Attachment.new(:name,
90
+ :instance,
91
+ :url_generator => mock_url_generator_builder,
92
+ :use_timestamp => false)
93
+
94
+ attachment.url(:style_name, :timestamp => true)
95
+ assert mock_url_generator_builder.has_generated_url_with_options?(:escape => true, :timestamp => true)
37
96
  end
38
97
 
39
- should "return the url by executing and interpolating the default_url when assigned with symbol as method in attachment model" do
40
- @attachment = attachment :default_url => :some_method_to_determine_default_url
98
+ should "return the path based on the url by default" do
99
+ @attachment = attachment :url => "/:class/:id/:basename"
41
100
  @model = @attachment.instance
42
- @model.stubs(:some_method_to_determine_default_url).returns(":class/female_:style_blegga.png")
43
- assert_equal "fake_models/female_foostyle_blegga.png", @attachment.url(:foostyle)
101
+ @model.id = 1234
102
+ @model.avatar_file_name = "fake.jpg"
103
+ assert_equal "#{Rails.root}/public/fake_models/1234/fake", @attachment.path
44
104
  end
45
105
 
46
106
  context "Attachment default_options" do
@@ -85,7 +145,7 @@ class AttachmentTest < Test::Unit::TestCase
85
145
  Paperclip::Attachment.default_options.keys.each do |key|
86
146
  should "be the default_options for #{key}" do
87
147
  assert_equal @old_default_options[key],
88
- @attachment.options.send(key),
148
+ @attachment.instance_variable_get("@options")[key],
89
149
  key
90
150
  end
91
151
  end
@@ -100,7 +160,7 @@ class AttachmentTest < Test::Unit::TestCase
100
160
  Paperclip::Attachment.default_options.keys.each do |key|
101
161
  should "be the new default_options for #{key}" do
102
162
  assert_equal @new_default_options[key],
103
- @attachment.options.send(key),
163
+ @attachment.instance_variable_get("@options")[key],
104
164
  key
105
165
  end
106
166
  end
@@ -160,36 +220,6 @@ class AttachmentTest < Test::Unit::TestCase
160
220
  end
161
221
  end
162
222
 
163
- context "An attachment" do
164
- setup do
165
- @file = StringIO.new("...")
166
- end
167
-
168
- context "using default time zone" do
169
- setup do
170
- rebuild_model :url => "X"
171
- @dummy = Dummy.new
172
- @dummy.avatar = @file
173
- end
174
-
175
- should "generate a url with a timestamp when passing true" do
176
- assert_equal "X?#{@dummy.avatar_updated_at.to_i.to_s}", @dummy.avatar.url(:style, true)
177
- end
178
-
179
- should "not generate a url with a timestamp when passing false" do
180
- assert_equal "X", @dummy.avatar.url(:style, false)
181
- end
182
-
183
- should "generate a url with a timestamp when setting a timestamp option" do
184
- assert_equal "X?#{@dummy.avatar_updated_at.to_i.to_s}", @dummy.avatar.url(:style, :timestamp => true)
185
- end
186
-
187
- should "not generate a url with a timestamp when setting a timestamp option to false" do
188
- assert_equal "X", @dummy.avatar.url(:style, :timestamp => false)
189
- end
190
- end
191
- end
192
-
193
223
  context "An attachment with :hash interpolations" do
194
224
  setup do
195
225
  @file = StringIO.new("...")
@@ -214,12 +244,12 @@ class AttachmentTest < Test::Unit::TestCase
214
244
  end
215
245
 
216
246
  should "interpolate the hash data" do
217
- @attachment.expects(:interpolate).with(@attachment.options.hash_data,anything).returns("interpolated_stuff")
218
- @attachment.hash
247
+ @attachment.expects(:interpolate).with(@attachment.options[:hash_data],anything).returns("interpolated_stuff")
248
+ @attachment.hash_key
219
249
  end
220
250
 
221
251
  should "result in the correct interpolation" do
222
- assert_equal "fake_models/avatars/1234/original/1234567890", @attachment.send(:interpolate,@attachment.options.hash_data)
252
+ assert_equal "fake_models/avatars/1234/original/1234567890", @attachment.send(:interpolate,@attachment.options[:hash_data])
223
253
  end
224
254
 
225
255
  should "result in a correct hash" do
@@ -302,7 +332,7 @@ class AttachmentTest < Test::Unit::TestCase
302
332
  end
303
333
 
304
334
  should "report the correct options when sent #extra_source_file_options_for(:thumb)" do
305
- assert_equal "-depth 8 -density 400", @dummy.avatar.send(:extra_source_file_options_for, :thumb), @dummy.avatar.options.source_file_options.inspect
335
+ assert_equal "-depth 8 -density 400", @dummy.avatar.send(:extra_source_file_options_for, :thumb), @dummy.avatar.source_file_options.inspect
306
336
  end
307
337
 
308
338
  should "report the correct options when sent #extra_source_file_options_for(:large)" do
@@ -384,10 +414,10 @@ class AttachmentTest < Test::Unit::TestCase
384
414
  end
385
415
 
386
416
  should "have the correct geometry" do
387
- assert_equal "50x50#", @attachment.options.styles[:thumb][:geometry]
417
+ assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
388
418
  end
389
419
  end
390
-
420
+
391
421
  context "An attachment with conditional :styles that is a proc" do
392
422
  setup do
393
423
  rebuild_model :styles => lambda{ |attachment| attachment.instance.other == 'a' ? {:thumb => "50x50#"} : {:large => "400x400"} }
@@ -396,34 +426,13 @@ class AttachmentTest < Test::Unit::TestCase
396
426
  end
397
427
 
398
428
  should "have the correct styles for the assigned instance values" do
399
- assert_equal "50x50#", @dummy.avatar.options.styles[:thumb][:geometry]
400
- assert_nil @dummy.avatar.options.styles[:large]
429
+ assert_equal "50x50#", @dummy.avatar.styles[:thumb][:geometry]
430
+ assert_nil @dummy.avatar.styles[:large]
401
431
 
402
432
  @dummy.other = 'b'
403
-
404
- assert_equal "400x400", @dummy.avatar.options.styles[:large][:geometry]
405
- assert_nil @dummy.avatar.options.styles[:thumb]
406
- end
407
- end
408
-
409
- context "An attachment with :url that is a proc" do
410
- setup do
411
- rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
412
-
413
- @file = File.new(File.join(File.dirname(__FILE__),
414
- "fixtures",
415
- "5k.png"), 'rb')
416
- @dummyA = Dummy.new(:other => 'a')
417
- @dummyA.avatar = @file
418
- @dummyB = Dummy.new(:other => 'b')
419
- @dummyB.avatar = @file
420
- end
421
433
 
422
- teardown { @file.close }
423
-
424
- should "return correct url" do
425
- assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
426
- assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
434
+ assert_equal "400x400", @dummy.avatar.styles[:large][:geometry]
435
+ assert_nil @dummy.avatar.styles[:thumb]
427
436
  end
428
437
  end
429
438
 
@@ -446,7 +455,7 @@ class AttachmentTest < Test::Unit::TestCase
446
455
  end
447
456
 
448
457
  should "have the correct geometry" do
449
- assert_equal "50x50#", @attachment.options.styles[:normal][:geometry]
458
+ assert_equal "50x50#", @attachment.styles[:normal][:geometry]
450
459
  end
451
460
  end
452
461
  end
@@ -464,7 +473,7 @@ class AttachmentTest < Test::Unit::TestCase
464
473
 
465
474
  [:processors, :whiny, :convert_options, :geometry, :format].each do |field|
466
475
  should "have the same #{field} field" do
467
- assert_equal @attachment.options.styles[:normal][field], @attachment.options.styles[:hash][field]
476
+ assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
468
477
  end
469
478
  end
470
479
  end
@@ -485,7 +494,7 @@ class AttachmentTest < Test::Unit::TestCase
485
494
  end
486
495
 
487
496
  should "have the correct processors" do
488
- assert_equal [ :test ], @attachment.options.styles[:normal][:processors]
497
+ assert_equal [ :test ], @attachment.styles[:normal][:processors]
489
498
  end
490
499
  end
491
500
  end
@@ -552,16 +561,16 @@ class AttachmentTest < Test::Unit::TestCase
552
561
  rebuild_model :storage => :FileSystem
553
562
  @dummy = Dummy.new
554
563
  assert @dummy.avatar.is_a?(Paperclip::Storage::Filesystem)
555
-
564
+
556
565
  rebuild_model :storage => :Filesystem
557
566
  @dummy = Dummy.new
558
567
  assert @dummy.avatar.is_a?(Paperclip::Storage::Filesystem)
559
568
  end
560
-
569
+
561
570
  should "convert underscored storage name to camelcase" do
562
571
  rebuild_model :storage => :not_here
563
572
  @dummy = Dummy.new
564
- exception = assert_raises(Paperclip::StorageMethodNotFound) do |e|
573
+ exception = assert_raises(Paperclip::StorageMethodNotFound) do
565
574
  @dummy.avatar
566
575
  end
567
576
  assert exception.message.include?("NotHere")
@@ -770,12 +779,6 @@ class AttachmentTest < Test::Unit::TestCase
770
779
  end
771
780
  end
772
781
 
773
- should "return its default_url when no file assigned" do
774
- assert @attachment.to_file.nil?
775
- assert_equal "/avatars/original/missing.png", @attachment.url
776
- assert_equal "/avatars/blah/missing.png", @attachment.url(:blah)
777
- end
778
-
779
782
  should "return nil as path when no file assigned" do
780
783
  assert @attachment.to_file.nil?
781
784
  assert_equal nil, @attachment.path
@@ -802,29 +805,6 @@ class AttachmentTest < Test::Unit::TestCase
802
805
  @attachment.stubs(:instance_read).with(:updated_at).returns(dtnow)
803
806
  end
804
807
 
805
- should "return a correct url even if the file does not exist" do
806
- assert_nil @attachment.to_file
807
- assert_match %r{^/system/avatars/#{@instance.id}/blah/5k\.png}, @attachment.url(:blah)
808
- end
809
-
810
- should "make sure the updated_at mtime is in the url if it is defined" do
811
- assert_match %r{#{@now.to_i}$}, @attachment.url(:blah)
812
- end
813
-
814
- should "make sure the updated_at mtime is NOT in the url if false is passed to the url method" do
815
- assert_no_match %r{#{@now.to_i}$}, @attachment.url(:blah, false)
816
- end
817
-
818
- context "with the updated_at field removed" do
819
- setup do
820
- @attachment.stubs(:instance_read).with(:updated_at).returns(nil)
821
- end
822
-
823
- should "only return the url without the updated_at when sent #url" do
824
- assert_match "/avatars/#{@instance.id}/blah/5k.png", @attachment.url(:blah)
825
- end
826
- end
827
-
828
808
  should "return the proper path when filename has a single .'s" do
829
809
  assert_equal File.expand_path("./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png"), File.expand_path(@attachment.path)
830
810
  end
@@ -864,14 +844,6 @@ class AttachmentTest < Test::Unit::TestCase
864
844
  @attachment.save
865
845
  end
866
846
 
867
- should "return the real url" do
868
- file = @attachment.to_file
869
- assert file
870
- assert_match %r{^/system/avatars/#{@instance.id}/original/5k\.png}, @attachment.url
871
- assert_match %r{^/system/avatars/#{@instance.id}/small/5k\.jpg}, @attachment.url(:small)
872
- file.close
873
- end
874
-
875
847
  should "commit the files to disk" do
876
848
  [:large, :medium, :small].each do |style|
877
849
  io = @attachment.to_file(style)
@@ -902,7 +874,7 @@ class AttachmentTest < Test::Unit::TestCase
902
874
 
903
875
  context "and trying to delete" do
904
876
  setup do
905
- @existing_names = @attachment.options.styles.keys.collect do |style|
877
+ @existing_names = @attachment.styles.keys.collect do |style|
906
878
  @attachment.path(style)
907
879
  end
908
880
  end
@@ -935,28 +907,47 @@ class AttachmentTest < Test::Unit::TestCase
935
907
  @attachment.destroy
936
908
  @existing_names.each{|f| assert ! File.exists?(f) }
937
909
  end
910
+
911
+ context "when keeping old files" do
912
+ setup do
913
+ @attachment.options[:keep_old_files] = true
914
+ end
915
+
916
+ should "keep the files after assigning nil" do
917
+ @attachment.expects(:instance_write).with(:file_name, nil)
918
+ @attachment.expects(:instance_write).with(:content_type, nil)
919
+ @attachment.expects(:instance_write).with(:file_size, nil)
920
+ @attachment.expects(:instance_write).with(:updated_at, nil)
921
+ @attachment.assign nil
922
+ @attachment.save
923
+ @existing_names.each{|f| assert File.exists?(f) }
924
+ end
925
+
926
+ should "keep the files when you call #clear and #save" do
927
+ @attachment.expects(:instance_write).with(:file_name, nil)
928
+ @attachment.expects(:instance_write).with(:content_type, nil)
929
+ @attachment.expects(:instance_write).with(:file_size, nil)
930
+ @attachment.expects(:instance_write).with(:updated_at, nil)
931
+ @attachment.clear
932
+ @attachment.save
933
+ @existing_names.each{|f| assert File.exists?(f) }
934
+ end
935
+
936
+ should "keep the files when you call #delete" do
937
+ @attachment.expects(:instance_write).with(:file_name, nil)
938
+ @attachment.expects(:instance_write).with(:content_type, nil)
939
+ @attachment.expects(:instance_write).with(:file_size, nil)
940
+ @attachment.expects(:instance_write).with(:updated_at, nil)
941
+ @attachment.destroy
942
+ @existing_names.each{|f| assert File.exists?(f) }
943
+ end
944
+ end
938
945
  end
939
946
  end
940
947
  end
941
948
  end
942
949
  end
943
950
 
944
- context "with a file that has space in file name" do
945
- setup do
946
- @attachment.stubs(:instance_read).with(:file_name).returns("spaced file.png")
947
- @attachment.stubs(:instance_read).with(:content_type).returns("image/png")
948
- @attachment.stubs(:instance_read).with(:file_size).returns(12345)
949
- dtnow = DateTime.now
950
- @now = Time.now
951
- Time.stubs(:now).returns(@now)
952
- @attachment.stubs(:instance_read).with(:updated_at).returns(dtnow)
953
- end
954
-
955
- should "returns an escaped version of the URL" do
956
- assert_match /\/spaced%20file\.png/, @attachment.url
957
- end
958
- end
959
-
960
951
  context "when trying a nonexistant storage type" do
961
952
  setup do
962
953
  rebuild_model :storage => :not_here
@@ -1020,7 +1011,18 @@ class AttachmentTest < Test::Unit::TestCase
1020
1011
  assert_equal now.to_i, @dummy.avatar.updated_at
1021
1012
  end
1022
1013
  end
1023
-
1014
+
1015
+ should "not calculate fingerprint after save" do
1016
+ @dummy.avatar = @file
1017
+ @dummy.save
1018
+ assert_nil @dummy.avatar.fingerprint
1019
+ end
1020
+
1021
+ should "not calculate fingerprint before saving" do
1022
+ @dummy.avatar = @file
1023
+ assert_nil @dummy.avatar.fingerprint
1024
+ end
1025
+
1024
1026
  context "and avatar_content_type column" do
1025
1027
  setup do
1026
1028
  ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
@@ -1109,21 +1111,6 @@ class AttachmentTest < Test::Unit::TestCase
1109
1111
  end
1110
1112
  end
1111
1113
 
1112
- context "setting an interpolation class" do
1113
- should "produce the URL with the given interpolations" do
1114
- Interpolator = Class.new do
1115
- def self.interpolate(pattern, attachment, style_name)
1116
- "hello"
1117
- end
1118
- end
1119
-
1120
- instance = Dummy.new
1121
- attachment = Paperclip::Attachment.new(:avatar, instance, :interpolator => Interpolator)
1122
-
1123
- assert_equal "hello", attachment.url
1124
- end
1125
- end
1126
-
1127
1114
  context "An attached file" do
1128
1115
  setup do
1129
1116
  rebuild_model