paperclip 4.2.2 → 5.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +5 -9
  9. data/LICENSE +1 -1
  10. data/NEWS +148 -31
  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 +6 -8
  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 +18 -15
  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 +34 -11
  91. data/spec/paperclip/paperclip_spec.rb +4 -29
  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 +109 -162
  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.0.0')
26
- s.add_dependency('activesupport', '>= 3.0.0')
27
- s.add_dependency('cocaine', '~> 0.5.3')
27
+ s.add_dependency('activemodel', '>= 4.2.0')
28
+ s.add_dependency('activesupport', '>= 4.2.0')
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.0.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')
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.0.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