paperclip 4.2.4 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +17 -0
  3. data/.hound.yml +1055 -0
  4. data/.rubocop.yml +1 -0
  5. data/.travis.yml +17 -15
  6. data/Appraisals +4 -16
  7. data/CONTRIBUTING.md +19 -8
  8. data/Gemfile +4 -8
  9. data/LICENSE +1 -1
  10. data/NEWS +105 -2
  11. data/README.md +327 -191
  12. data/RELEASING.md +17 -0
  13. data/Rakefile +2 -2
  14. data/UPGRADING +12 -9
  15. data/features/basic_integration.feature +10 -6
  16. data/features/migration.feature +0 -24
  17. data/features/step_definitions/attachment_steps.rb +33 -27
  18. data/features/step_definitions/html_steps.rb +2 -2
  19. data/features/step_definitions/rails_steps.rb +39 -38
  20. data/features/step_definitions/s3_steps.rb +2 -2
  21. data/features/step_definitions/web_steps.rb +1 -103
  22. data/features/support/env.rb +1 -0
  23. data/features/support/file_helpers.rb +2 -2
  24. data/features/support/paths.rb +1 -1
  25. data/features/support/rails.rb +0 -24
  26. data/gemfiles/4.2.gemfile +5 -7
  27. data/gemfiles/5.0.gemfile +17 -0
  28. data/lib/paperclip/attachment.rb +32 -20
  29. data/lib/paperclip/attachment_registry.rb +3 -2
  30. data/lib/paperclip/callbacks.rb +8 -6
  31. data/lib/paperclip/content_type_detector.rb +27 -11
  32. data/lib/paperclip/errors.rb +3 -1
  33. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  34. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  35. data/lib/paperclip/glue.rb +1 -1
  36. data/lib/paperclip/has_attached_file.rb +9 -2
  37. data/lib/paperclip/helpers.rb +14 -10
  38. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  39. data/lib/paperclip/interpolations.rb +19 -14
  40. data/lib/paperclip/io_adapters/abstract_adapter.rb +26 -3
  41. data/lib/paperclip/io_adapters/attachment_adapter.rb +10 -5
  42. data/lib/paperclip/io_adapters/data_uri_adapter.rb +8 -8
  43. data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
  44. data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
  45. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +7 -7
  46. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  47. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  48. data/lib/paperclip/io_adapters/registry.rb +6 -2
  49. data/lib/paperclip/io_adapters/stringio_adapter.rb +9 -6
  50. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
  51. data/lib/paperclip/io_adapters/uri_adapter.rb +41 -19
  52. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  53. data/lib/paperclip/media_type_spoof_detector.rb +2 -2
  54. data/lib/paperclip/processor.rb +5 -4
  55. data/lib/paperclip/rails_environment.rb +25 -0
  56. data/lib/paperclip/schema.rb +3 -9
  57. data/lib/paperclip/storage/filesystem.rb +13 -2
  58. data/lib/paperclip/storage/fog.rb +30 -18
  59. data/lib/paperclip/storage/s3.rb +92 -65
  60. data/lib/paperclip/thumbnail.rb +16 -7
  61. data/lib/paperclip/url_generator.rb +16 -13
  62. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  63. data/lib/paperclip/validators.rb +1 -1
  64. data/lib/paperclip/version.rb +3 -1
  65. data/lib/paperclip.rb +25 -12
  66. data/lib/tasks/paperclip.rake +33 -3
  67. data/paperclip.gemspec +17 -14
  68. data/spec/paperclip/attachment_definitions_spec.rb +1 -1
  69. data/spec/paperclip/attachment_processing_spec.rb +2 -4
  70. data/spec/paperclip/attachment_registry_spec.rb +84 -13
  71. data/spec/paperclip/attachment_spec.rb +130 -39
  72. data/spec/paperclip/content_type_detector_spec.rb +8 -1
  73. data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -1
  74. data/spec/paperclip/geometry_spec.rb +1 -1
  75. data/spec/paperclip/glue_spec.rb +44 -0
  76. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  77. data/spec/paperclip/integration_spec.rb +4 -3
  78. data/spec/paperclip/interpolations_spec.rb +16 -13
  79. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +47 -23
  80. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +6 -3
  81. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +7 -1
  82. data/spec/paperclip/io_adapters/file_adapter_spec.rb +6 -3
  83. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +26 -6
  84. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
  85. data/spec/paperclip/io_adapters/registry_spec.rb +2 -2
  86. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +5 -1
  87. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +5 -5
  88. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +77 -7
  89. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  90. data/spec/paperclip/media_type_spoof_detector_spec.rb +28 -5
  91. data/spec/paperclip/paperclip_spec.rb +3 -28
  92. data/spec/paperclip/plural_cache_spec.rb +17 -16
  93. data/spec/paperclip/rails_environment_spec.rb +33 -0
  94. data/spec/paperclip/storage/fog_spec.rb +58 -3
  95. data/spec/paperclip/storage/s3_live_spec.rb +20 -14
  96. data/spec/paperclip/storage/s3_spec.rb +398 -213
  97. data/spec/paperclip/tempfile_factory_spec.rb +4 -0
  98. data/spec/paperclip/tempfile_spec.rb +35 -0
  99. data/spec/paperclip/thumbnail_spec.rb +51 -32
  100. data/spec/paperclip/url_generator_spec.rb +55 -44
  101. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  102. data/spec/paperclip/validators_spec.rb +5 -5
  103. data/spec/spec_helper.rb +8 -1
  104. data/spec/support/assertions.rb +12 -1
  105. data/spec/support/conditional_filter_helper.rb +5 -0
  106. data/spec/support/fake_model.rb +4 -0
  107. data/spec/support/fixtures/empty.xlsx +0 -0
  108. data/spec/support/matchers/have_column.rb +11 -2
  109. data/spec/support/mock_attachment.rb +2 -0
  110. data/spec/support/mock_url_generator_builder.rb +2 -2
  111. data/spec/support/model_reconstruction.rb +9 -1
  112. data/spec/support/reporting.rb +11 -0
  113. metadata +105 -164
  114. data/RUNNING_TESTS.md +0 -4
  115. data/cucumber/paperclip_steps.rb +0 -6
  116. data/gemfiles/3.2.gemfile +0 -19
  117. data/gemfiles/4.0.gemfile +0 -19
  118. data/gemfiles/4.1.gemfile +0 -19
  119. data/lib/paperclip/locales/de.yml +0 -18
  120. data/lib/paperclip/locales/es.yml +0 -18
  121. data/lib/paperclip/locales/ja.yml +0 -18
  122. data/lib/paperclip/locales/pt-BR.yml +0 -18
  123. data/lib/paperclip/locales/zh-CN.yml +0 -18
  124. data/lib/paperclip/locales/zh-HK.yml +0 -18
  125. data/lib/paperclip/locales/zh-TW.yml +0 -18
  126. data/spec/support/mock_model.rb +0 -2
  127. data/spec/support/rails_helpers.rb +0 -7
data/paperclip.gemspec CHANGED
@@ -12,40 +12,43 @@ Gem::Specification.new do |s|
12
12
  s.description = "Easy upload management for ActiveRecord"
13
13
  s.license = "MIT"
14
14
 
15
- s.rubyforge_project = "paperclip"
16
-
17
15
  s.files = `git ls-files`.split("\n")
18
16
  s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
19
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
18
  s.require_paths = ["lib"]
21
19
 
20
+ if File.exist?('UPGRADING')
21
+ s.post_install_message = File.read("UPGRADING")
22
+ end
23
+
22
24
  s.requirements << "ImageMagick"
23
- s.required_ruby_version = ">= 1.9.2"
25
+ s.required_ruby_version = ">= 2.1.0"
24
26
 
25
- s.add_dependency('activemodel', '>= 3.2.0')
26
- s.add_dependency('activesupport', '>= 3.2.0')
27
+ s.add_dependency('activemodel', '>= 4.2.0')
28
+ s.add_dependency('activesupport', '>= 4.2.0')
27
29
  s.add_dependency('cocaine', '~> 0.5.5')
28
30
  s.add_dependency('mime-types')
31
+ s.add_dependency('mimemagic', '~> 0.3.0')
29
32
 
30
- s.add_development_dependency('activerecord', '>= 3.2.0')
33
+ s.add_development_dependency('activerecord', '>= 4.2.0')
31
34
  s.add_development_dependency('shoulda')
32
- s.add_development_dependency('rspec')
35
+ s.add_development_dependency('rspec', '~> 3.0')
33
36
  s.add_development_dependency('appraisal')
34
37
  s.add_development_dependency('mocha')
35
- s.add_development_dependency('aws-sdk', '>= 1.5.7', "<= 2.0")
38
+ s.add_development_dependency('aws-sdk', '>= 2.3.0', '< 3.0')
36
39
  s.add_development_dependency('bourne')
37
- s.add_development_dependency('cucumber', '~> 1.3.11')
38
- s.add_development_dependency('aruba')
40
+ s.add_development_dependency('cucumber-rails')
41
+ s.add_development_dependency('cucumber-expressions', '4.0.3') # TODO: investigate failures on 4.0.4
42
+ s.add_development_dependency('aruba', '~> 0.9.0')
39
43
  s.add_development_dependency('nokogiri')
40
- # Ruby version < 1.9.3 can't install capybara > 2.0.3.
41
- s.add_development_dependency('capybara', '= 2.0.3')
44
+ s.add_development_dependency('capybara')
42
45
  s.add_development_dependency('bundler')
43
- s.add_development_dependency('fog', '~> 1.0')
46
+ s.add_development_dependency('fog-aws')
47
+ s.add_development_dependency('fog-local')
44
48
  s.add_development_dependency('launchy')
45
49
  s.add_development_dependency('rake')
46
50
  s.add_development_dependency('fakeweb')
47
51
  s.add_development_dependency('railties')
48
- s.add_development_dependency('actionmailer', '>= 3.2.0')
49
52
  s.add_development_dependency('generator_spec')
50
53
  s.add_development_dependency('timecop')
51
54
  end
@@ -8,6 +8,6 @@ describe "Attachment Definitions" do
8
8
  Dummy.do_not_validate_attachment_file_type :avatar
9
9
  expected = {avatar: {path: "abc"}, other_attachment: {url: "123"}}
10
10
 
11
- assert_equal expected, Dummy.attachment_definitions
11
+ expect(Dummy.attachment_definitions).to eq expected
12
12
  end
13
13
  end
@@ -2,11 +2,9 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'Attachment Processing' do
5
- context 'using validates_attachment_content_type' do
6
- before do
7
- rebuild_class
8
- end
5
+ before { rebuild_class }
9
6
 
7
+ context 'using validates_attachment_content_type' do
10
8
  it 'processes attachments given a valid assignment' do
11
9
  file = File.new(fixture_file("5k.png"))
12
10
  Dummy.validates_attachment_content_type :avatar, content_type: "image/png"
@@ -31,8 +31,8 @@ describe 'Attachment Registry' do
31
31
  it 'calls the block with the class, attachment name, and options' do
32
32
  foo = Class.new
33
33
  expected_accumulations = [
34
- [foo, :avatar, { yo: 'greeting' }],
35
- [foo, :greeter, { ciao: 'greeting' }]
34
+ [foo, :avatar, { yo: "greeting" }],
35
+ [foo, :greeter, { ciao: "greeting" }]
36
36
  ]
37
37
  expected_accumulations.each do |args|
38
38
  Paperclip::AttachmentRegistry.register(*args)
@@ -50,25 +50,92 @@ describe 'Attachment Registry' do
50
50
  context '.definitions_for' do
51
51
  it 'produces the attachment name and options' do
52
52
  expected_definitions = {
53
- avatar: { yo: 'greeting' },
54
- greeter: { ciao: 'greeting' }
53
+ avatar: { yo: "greeting" },
54
+ greeter: { ciao: "greeting" }
55
55
  }
56
56
  foo = Class.new
57
- Paperclip::AttachmentRegistry.register(foo, :avatar, { yo: 'greeting' })
58
- Paperclip::AttachmentRegistry.register(foo, :greeter, { ciao: 'greeting' })
57
+ Paperclip::AttachmentRegistry.register(
58
+ foo,
59
+ :avatar,
60
+ yo: "greeting"
61
+ )
62
+ Paperclip::AttachmentRegistry.register(
63
+ foo,
64
+ :greeter,
65
+ ciao: "greeting"
66
+ )
59
67
 
60
68
  definitions = Paperclip::AttachmentRegistry.definitions_for(foo)
61
69
 
62
70
  assert_equal expected_definitions, definitions
63
71
  end
64
72
 
65
- it "produces defintions for subclasses" do
66
- expected_definitions = { avatar: { yo: 'greeting' } }
67
- Foo = Class.new
68
- Bar = Class.new(Foo)
69
- Paperclip::AttachmentRegistry.register(Foo, :avatar, expected_definitions[:avatar])
73
+ it 'produces defintions for subclasses' do
74
+ expected_definitions = { avatar: { yo: "greeting" } }
75
+ foo = Class.new
76
+ bar = Class.new(foo)
77
+ Paperclip::AttachmentRegistry.register(
78
+ foo,
79
+ :avatar,
80
+ expected_definitions[:avatar]
81
+ )
82
+
83
+ definitions = Paperclip::AttachmentRegistry.definitions_for(bar)
84
+
85
+ assert_equal expected_definitions, definitions
86
+ end
87
+
88
+ it 'produces defintions for subclasses but deep merging them' do
89
+ foo_definitions = { avatar: { yo: "greeting" } }
90
+ bar_definitions = { avatar: { ciao: "greeting" } }
91
+ expected_definitions = {
92
+ avatar: {
93
+ yo: "greeting",
94
+ ciao: "greeting"
95
+ }
96
+ }
97
+ foo = Class.new
98
+ bar = Class.new(foo)
99
+ Paperclip::AttachmentRegistry.register(
100
+ foo,
101
+ :avatar,
102
+ foo_definitions[:avatar]
103
+ )
104
+ Paperclip::AttachmentRegistry.register(
105
+ bar,
106
+ :avatar,
107
+ bar_definitions[:avatar]
108
+ )
109
+
110
+ definitions = Paperclip::AttachmentRegistry.definitions_for(bar)
70
111
 
71
- definitions = Paperclip::AttachmentRegistry.definitions_for(Bar)
112
+ assert_equal expected_definitions, definitions
113
+ end
114
+
115
+ it 'allows subclasses to override attachment defitions' do
116
+ foo_definitions = { avatar: { yo: "greeting" } }
117
+ bar_definitions = { avatar: { yo: "hello" } }
118
+
119
+ expected_definitions = {
120
+ avatar: {
121
+ yo: "hello"
122
+ }
123
+ }
124
+
125
+ foo = Class.new
126
+ bar = Class.new(foo)
127
+ Paperclip::AttachmentRegistry.register(
128
+ foo,
129
+ :avatar,
130
+ foo_definitions[:avatar]
131
+ )
132
+ Paperclip::AttachmentRegistry.register(
133
+ bar,
134
+ :avatar,
135
+ bar_definitions[:avatar]
136
+ )
137
+
138
+ definitions = Paperclip::AttachmentRegistry.definitions_for(bar)
72
139
 
73
140
  assert_equal expected_definitions, definitions
74
141
  end
@@ -77,7 +144,11 @@ describe 'Attachment Registry' do
77
144
  context '.clear' do
78
145
  it 'removes all of the existing attachment definitions' do
79
146
  foo = Class.new
80
- Paperclip::AttachmentRegistry.register(foo, :greeter, { ciao: 'greeting' })
147
+ Paperclip::AttachmentRegistry.register(
148
+ foo,
149
+ :greeter,
150
+ ciao: "greeting"
151
+ )
81
152
 
82
153
  Paperclip::AttachmentRegistry.clear
83
154
 
@@ -13,7 +13,7 @@ describe Paperclip::Attachment do
13
13
  it "is present when the file is set" do
14
14
  rebuild_class
15
15
  dummy = Dummy.new
16
- dummy.avatar = File.new(fixture_file("50x50.png"), "rb")
16
+ dummy.avatar = File.new(fixture_file("50x50.png"), "rb")
17
17
  expect(dummy.avatar).to_not be_blank
18
18
  expect(dummy.avatar).to be_present
19
19
  end
@@ -34,9 +34,9 @@ describe Paperclip::Attachment do
34
34
  it "does not delete styles that don't get reprocessed" do
35
35
  file = File.new(fixture_file("50x50.png"), 'rb')
36
36
  rebuild_class styles: {
37
- small: '100x>',
38
- large: '500x>',
39
- original: '42x42#'
37
+ small: "100x>",
38
+ large: "500x>",
39
+ original: "42x42#"
40
40
  }
41
41
 
42
42
  dummy = Dummy.new
@@ -75,7 +75,11 @@ describe Paperclip::Attachment do
75
75
 
76
76
  it "handles a boolean second argument to #url" do
77
77
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
78
- attachment = Paperclip::Attachment.new(:name, :instance, url_generator: mock_url_generator_builder)
78
+ attachment = Paperclip::Attachment.new(
79
+ :name,
80
+ FakeModel.new,
81
+ url_generator: mock_url_generator_builder
82
+ )
79
83
 
80
84
  attachment.url(:style_name, true)
81
85
  expect(mock_url_generator_builder.has_generated_url_with_options?(timestamp: true, escape: true)).to eq true
@@ -86,7 +90,11 @@ describe Paperclip::Attachment do
86
90
 
87
91
  it "passes the style and options through to the URL generator on #url" do
88
92
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
89
- attachment = Paperclip::Attachment.new(:name, :instance, url_generator: mock_url_generator_builder)
93
+ attachment = Paperclip::Attachment.new(
94
+ :name,
95
+ FakeModel.new,
96
+ url_generator: mock_url_generator_builder
97
+ )
90
98
 
91
99
  attachment.url(:style_name, options: :values)
92
100
  expect(mock_url_generator_builder.has_generated_url_with_options?(options: :values)).to eq true
@@ -95,7 +103,7 @@ describe Paperclip::Attachment do
95
103
  it "passes default options through when #url is given one argument" do
96
104
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
97
105
  attachment = Paperclip::Attachment.new(:name,
98
- :instance,
106
+ FakeModel.new,
99
107
  url_generator: mock_url_generator_builder,
100
108
  use_timestamp: true)
101
109
 
@@ -106,7 +114,7 @@ describe Paperclip::Attachment do
106
114
  it "passes default style and options through when #url is given no arguments" do
107
115
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
108
116
  attachment = Paperclip::Attachment.new(:name,
109
- :instance,
117
+ FakeModel.new,
110
118
  default_style: 'default style',
111
119
  url_generator: mock_url_generator_builder,
112
120
  use_timestamp: true)
@@ -119,7 +127,7 @@ describe Paperclip::Attachment do
119
127
  it "passes the option timestamp: true if :use_timestamp is true and :timestamp is not passed" do
120
128
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
121
129
  attachment = Paperclip::Attachment.new(:name,
122
- :instance,
130
+ FakeModel.new,
123
131
  url_generator: mock_url_generator_builder,
124
132
  use_timestamp: true)
125
133
 
@@ -130,7 +138,7 @@ describe Paperclip::Attachment do
130
138
  it "passes the option timestamp: false if :use_timestamp is false and :timestamp is not passed" do
131
139
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
132
140
  attachment = Paperclip::Attachment.new(:name,
133
- :instance,
141
+ FakeModel.new,
134
142
  url_generator: mock_url_generator_builder,
135
143
  use_timestamp: false)
136
144
 
@@ -141,7 +149,7 @@ describe Paperclip::Attachment do
141
149
  it "does not change the :timestamp if :timestamp is passed" do
142
150
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
143
151
  attachment = Paperclip::Attachment.new(:name,
144
- :instance,
152
+ FakeModel.new,
145
153
  url_generator: mock_url_generator_builder,
146
154
  use_timestamp: false)
147
155
 
@@ -152,7 +160,7 @@ describe Paperclip::Attachment do
152
160
  it "renders JSON as default style" do
153
161
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
154
162
  attachment = Paperclip::Attachment.new(:name,
155
- :instance,
163
+ FakeModel.new,
156
164
  default_style: 'default style',
157
165
  url_generator: mock_url_generator_builder)
158
166
 
@@ -163,7 +171,7 @@ describe Paperclip::Attachment do
163
171
  it "passes the option escape: true if :escape_url is true and :escape is not passed" do
164
172
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
165
173
  attachment = Paperclip::Attachment.new(:name,
166
- :instance,
174
+ FakeModel.new,
167
175
  url_generator: mock_url_generator_builder,
168
176
  escape_url: true)
169
177
 
@@ -174,7 +182,7 @@ describe Paperclip::Attachment do
174
182
  it "passes the option escape: false if :escape_url is false and :escape is not passed" do
175
183
  mock_url_generator_builder = MockUrlGeneratorBuilder.new
176
184
  attachment = Paperclip::Attachment.new(:name,
177
- :instance,
185
+ FakeModel.new,
178
186
  url_generator: mock_url_generator_builder,
179
187
  escape_url: false)
180
188
 
@@ -212,10 +220,8 @@ describe Paperclip::Attachment do
212
220
  dummy = Dummy.new
213
221
  dummy.id = 1234
214
222
  dummy.avatar_file_name = "fake.jpg"
223
+ dummy.stubs(:new_record?).returns(false)
215
224
  expected_string = '{"avatar":"/system/dummies/avatars/000/001/234/original/fake.jpg"}'
216
- if ActiveRecord::Base.include_root_in_json # This is true by default in Rails 3, and false in 4
217
- expected_string = %({"dummy":#{expected_string}})
218
- end
219
225
  # active_model pre-3.2 checks only by calling any? on it, thus it doesn't work if it is empty
220
226
  assert_equal expected_string, dummy.to_json(only: [:dummy_key_for_old_active_model], methods: [:avatar])
221
227
  end
@@ -245,12 +251,17 @@ describe Paperclip::Attachment do
245
251
 
246
252
  context "without an Attachment" do
247
253
  before do
254
+ rebuild_model default_url: "default.url"
248
255
  @dummy = Dummy.new
249
256
  end
250
257
 
251
258
  it "returns false when asked exists?" do
252
259
  assert !@dummy.avatar.exists?
253
260
  end
261
+
262
+ it "#url returns the default_url" do
263
+ expect(@dummy.avatar.url).to eq "default.url"
264
+ end
254
265
  end
255
266
 
256
267
  context "on an Attachment" do
@@ -489,6 +500,7 @@ describe Paperclip::Attachment do
489
500
  @attachment.expects(:post_process).with(:thumb)
490
501
  @attachment.expects(:post_process).with(:large).never
491
502
  @attachment.assign(@file)
503
+ @attachment.save
492
504
  end
493
505
  end
494
506
 
@@ -635,15 +647,40 @@ describe Paperclip::Attachment do
635
647
  before do
636
648
  rebuild_model processor: [:thumbnail], styles: { small: '' }, whiny_thumbnails: true
637
649
  @dummy = Dummy.new
638
- Paperclip::Thumbnail.expects(:make).raises(Paperclip::Error, "cannot be processed.")
639
650
  @file = StringIO.new("...")
640
651
  @file.stubs(:to_tempfile).returns(@file)
641
- @dummy.avatar = @file
642
652
  end
643
653
 
644
- it "correctly forwards processing error message to the instance" do
645
- @dummy.valid?
646
- assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
654
+ context "when error is meaningful for the end user" do
655
+ before do
656
+ Paperclip::Thumbnail.expects(:make).raises(
657
+ Paperclip::Errors::NotIdentifiedByImageMagickError,
658
+ "cannot be processed."
659
+ )
660
+ end
661
+
662
+ it "correctly forwards processing error message to the instance" do
663
+ @dummy.avatar = @file
664
+ @dummy.valid?
665
+ assert_contains(
666
+ @dummy.errors.full_messages,
667
+ "Avatar cannot be processed."
668
+ )
669
+ end
670
+ end
671
+
672
+ context "when error is intended for the developer" do
673
+ before do
674
+ Paperclip::Thumbnail.expects(:make).raises(
675
+ Paperclip::Errors::CommandNotFoundError
676
+ )
677
+ end
678
+
679
+ it "propagates the error" do
680
+ assert_raises(Paperclip::Errors::CommandNotFoundError) do
681
+ @dummy.avatar = @file
682
+ end
683
+ end
647
684
  end
648
685
  end
649
686
 
@@ -661,9 +698,6 @@ describe Paperclip::Attachment do
661
698
 
662
699
  context "when assigned" do
663
700
  it "calls #make on all specified processors" do
664
- Paperclip::Thumbnail.stubs(:make).with(any_parameters).returns(@file)
665
- Paperclip::Test.stubs(:make).with(any_parameters).returns(@file)
666
-
667
701
  @dummy.avatar = @file
668
702
 
669
703
  expect(Paperclip::Thumbnail).to have_received(:make)
@@ -678,7 +712,6 @@ describe Paperclip::Attachment do
678
712
  convert_options: "",
679
713
  source_file_options: ""
680
714
  })
681
- Paperclip::Thumbnail.stubs(:make).returns(@file)
682
715
 
683
716
  @dummy.avatar = @file
684
717
 
@@ -686,12 +719,36 @@ describe Paperclip::Attachment do
686
719
  end
687
720
 
688
721
  it "calls #make with attachment passed as third argument" do
689
- Paperclip::Test.expects(:make).returns(@file)
690
-
691
722
  @dummy.avatar = @file
692
723
 
693
724
  expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
694
725
  end
726
+
727
+ it "calls #make and unlinks intermediary files afterward" do
728
+ @dummy.avatar.expects(:unlink_files).with([@file, @file])
729
+
730
+ @dummy.avatar = @file
731
+ end
732
+ end
733
+ end
734
+
735
+ context "An attachment with a processor that returns original file" do
736
+ before do
737
+ class Paperclip::Test < Paperclip::Processor
738
+ def make; @file; end
739
+ end
740
+ rebuild_model processors: [:test], styles: { once: "100x100" }
741
+ @file = StringIO.new("...")
742
+ @file.stubs(:close)
743
+ @dummy = Dummy.new
744
+ end
745
+
746
+ context "when assigned" do
747
+ it "#calls #make and doesn't unlink the original file" do
748
+ @dummy.avatar.expects(:unlink_files).with([])
749
+
750
+ @dummy.avatar = @file
751
+ end
695
752
  end
696
753
  end
697
754
 
@@ -1065,7 +1122,7 @@ describe Paperclip::Attachment do
1065
1122
  context "with a file assigned but not saved yet" do
1066
1123
  it "clears out any attached files" do
1067
1124
  @attachment.assign(@file)
1068
- assert !@attachment.queued_for_write.blank?
1125
+ assert @attachment.queued_for_write.present?
1069
1126
  @attachment.clear
1070
1127
  assert @attachment.queued_for_write.blank?
1071
1128
  end
@@ -1315,6 +1372,12 @@ describe Paperclip::Attachment do
1315
1372
  end
1316
1373
 
1317
1374
  it "does not calculate fingerprint" do
1375
+ Digest::MD5.stubs(:file)
1376
+ @dummy.avatar = @file
1377
+ expect(Digest::MD5).to have_received(:file).never
1378
+ end
1379
+
1380
+ it "does not assign fingerprint" do
1318
1381
  @dummy.avatar = @file
1319
1382
  assert_nil @dummy.avatar.fingerprint
1320
1383
  end
@@ -1371,16 +1434,46 @@ describe Paperclip::Attachment do
1371
1434
  assert_nothing_raised { @dummy.avatar = @file }
1372
1435
  end
1373
1436
 
1374
- it "returns the right value when sent #avatar_fingerprint" do
1375
- @dummy.avatar = @file
1376
- assert_equal 'aec488126c3b33c08a10c3fa303acf27', @dummy.avatar_fingerprint
1437
+ context "with explicitly set digest" do
1438
+ before do
1439
+ rebuild_class adapter_options: { hash_digest: Digest::SHA256 }
1440
+ @dummy = Dummy.new
1441
+ end
1442
+
1443
+ it "returns the right value when sent #avatar_fingerprint" do
1444
+ @dummy.avatar = @file
1445
+ assert_equal "734016d801a497f5579cdd4ef2ae1d020088c1db754dc434482d76dd5486520a",
1446
+ @dummy.avatar_fingerprint
1447
+ end
1448
+
1449
+ it "returns the right value when saved, reloaded, and sent #avatar_fingerprint" do
1450
+ @dummy.avatar = @file
1451
+ @dummy.save
1452
+ @dummy = Dummy.find(@dummy.id)
1453
+ assert_equal "734016d801a497f5579cdd4ef2ae1d020088c1db754dc434482d76dd5486520a",
1454
+ @dummy.avatar_fingerprint
1455
+ end
1377
1456
  end
1378
1457
 
1379
- it "returns the right value when saved, reloaded, and sent #avatar_fingerprint" do
1380
- @dummy.avatar = @file
1381
- @dummy.save
1382
- @dummy = Dummy.find(@dummy.id)
1383
- assert_equal 'aec488126c3b33c08a10c3fa303acf27', @dummy.avatar_fingerprint
1458
+ context "with the default digest" do
1459
+ before do
1460
+ rebuild_class # MD5 is the default
1461
+ @dummy = Dummy.new
1462
+ end
1463
+
1464
+ it "returns the right value when sent #avatar_fingerprint" do
1465
+ @dummy.avatar = @file
1466
+ assert_equal "aec488126c3b33c08a10c3fa303acf27",
1467
+ @dummy.avatar_fingerprint
1468
+ end
1469
+
1470
+ it "returns the right value when saved, reloaded, and sent #avatar_fingerprint" do
1471
+ @dummy.avatar = @file
1472
+ @dummy.save
1473
+ @dummy = Dummy.find(@dummy.id)
1474
+ assert_equal "aec488126c3b33c08a10c3fa303acf27",
1475
+ @dummy.avatar_fingerprint
1476
+ end
1384
1477
  end
1385
1478
  end
1386
1479
  end
@@ -1452,6 +1545,4 @@ describe Paperclip::Attachment do
1452
1545
  assert_file_exists(@path)
1453
1546
  end
1454
1547
  end
1455
-
1456
1548
  end
1457
-
@@ -1,6 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Paperclip::ContentTypeDetector do
4
+ it 'returns a meaningful content type for open xml spreadsheets' do
5
+ file = File.new(fixture_file("empty.xlsx"))
6
+ assert_equal "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
7
+ Paperclip::ContentTypeDetector.new(file.path).detect
8
+ end
9
+
4
10
  it 'gives a sensible default when the name is empty' do
5
11
  assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new("").detect
6
12
  end
@@ -13,7 +19,8 @@ describe Paperclip::ContentTypeDetector do
13
19
 
14
20
  it 'returns content type of file if it is an acceptable type' do
15
21
  MIME::Types.stubs(:type_for).returns([MIME::Type.new('application/mp4'), MIME::Type.new('video/mp4'), MIME::Type.new('audio/mp4')])
16
- Paperclip.stubs(:run).returns("video/mp4")
22
+ Paperclip::ContentTypeDetector.any_instance
23
+ .stubs(:type_from_file_contents).returns("video/mp4")
17
24
  @filename = "my_file.mp4"
18
25
  assert_equal "video/mp4", Paperclip::ContentTypeDetector.new(@filename).detect
19
26
  end
@@ -24,4 +24,3 @@ describe Paperclip::FileCommandContentTypeDetector do
24
24
  Paperclip::FileCommandContentTypeDetector.new("windows").detect
25
25
  end
26
26
  end
27
-
@@ -82,7 +82,7 @@ describe Paperclip::Geometry do
82
82
  assert_equal 456, @upper.height
83
83
  end
84
84
 
85
- ['>', '<', '#', '@', '%', '^', '!', nil].each do |mod|
85
+ ['>', '<', '#', '@', '@>', '>@', '%', '^', '!', nil].each do |mod|
86
86
  it "ensures the modifier #{description} is preserved" do
87
87
  assert @geo = Paperclip::Geometry.parse("123x456#{mod}")
88
88
  assert_equal mod, @geo.modifier
@@ -0,0 +1,44 @@
1
+ # require "spec_helper"
2
+
3
+ describe Paperclip::Glue do
4
+ describe "when ActiveRecord does not exist" do
5
+ before do
6
+ ActiveRecordSaved = ActiveRecord
7
+ Object.send :remove_const, "ActiveRecord"
8
+ end
9
+
10
+ after do
11
+ ActiveRecord = ActiveRecordSaved
12
+ Object.send :remove_const, "ActiveRecordSaved"
13
+ end
14
+
15
+ it "does not fail" do
16
+ NonActiveRecordModel = Class.new
17
+ NonActiveRecordModel.send :include, Paperclip::Glue
18
+ Object.send :remove_const, "NonActiveRecordModel"
19
+ end
20
+ end
21
+
22
+ describe "when ActiveRecord does exist" do
23
+ before do
24
+ if Object.const_defined?("ActiveRecord")
25
+ @defined_active_record = false
26
+ else
27
+ ActiveRecord = :defined
28
+ @defined_active_record = true
29
+ end
30
+ end
31
+
32
+ after do
33
+ if @defined_active_record
34
+ Object.send :remove_const, "ActiveRecord"
35
+ end
36
+ end
37
+
38
+ it "does not fail" do
39
+ NonActiveRecordModel = Class.new
40
+ NonActiveRecordModel.send :include, Paperclip::Glue
41
+ Object.send :remove_const, "NonActiveRecordModel"
42
+ end
43
+ end
44
+ end