paperclip 4.2.2 → 5.0.0
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.
- checksums.yaml +4 -4
- data/.hound.yml +1066 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +18 -15
- data/Appraisals +20 -12
- data/CONTRIBUTING.md +19 -8
- data/Gemfile +4 -9
- data/LICENSE +1 -1
- data/NEWS +101 -31
- data/README.md +243 -159
- data/RELEASING.md +17 -0
- data/Rakefile +1 -1
- data/UPGRADING +12 -9
- data/features/basic_integration.feature +8 -4
- data/features/migration.feature +0 -24
- data/features/step_definitions/attachment_steps.rb +27 -21
- data/features/step_definitions/html_steps.rb +2 -2
- data/features/step_definitions/rails_steps.rb +11 -17
- data/features/step_definitions/s3_steps.rb +2 -2
- data/features/step_definitions/web_steps.rb +1 -103
- data/features/support/file_helpers.rb +2 -2
- data/gemfiles/4.2.awsv2.0.gemfile +17 -0
- data/gemfiles/4.2.awsv2.1.gemfile +17 -0
- data/gemfiles/{4.1.gemfile → 4.2.awsv2.gemfile} +4 -3
- data/gemfiles/5.0.awsv2.0.gemfile +17 -0
- data/gemfiles/5.0.awsv2.1.gemfile +17 -0
- data/gemfiles/{4.2.gemfile → 5.0.awsv2.gemfile} +4 -3
- data/lib/paperclip/attachment.rb +19 -16
- data/lib/paperclip/attachment_registry.rb +3 -2
- data/lib/paperclip/callbacks.rb +8 -6
- data/lib/paperclip/content_type_detector.rb +27 -11
- data/lib/paperclip/errors.rb +3 -1
- data/lib/paperclip/file_command_content_type_detector.rb +6 -8
- data/lib/paperclip/geometry_parser_factory.rb +1 -1
- data/lib/paperclip/glue.rb +1 -1
- data/lib/paperclip/has_attached_file.rb +9 -2
- data/lib/paperclip/helpers.rb +14 -10
- data/lib/paperclip/interpolations/plural_cache.rb +6 -5
- data/lib/paperclip/interpolations.rb +18 -13
- data/lib/paperclip/io_adapters/abstract_adapter.rb +1 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
- data/lib/paperclip/io_adapters/uri_adapter.rb +3 -1
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +2 -2
- data/lib/paperclip/rails_environment.rb +25 -0
- data/lib/paperclip/schema.rb +3 -9
- data/lib/paperclip/storage/fog.rb +21 -12
- data/lib/paperclip/storage/s3.rb +51 -50
- data/lib/paperclip/thumbnail.rb +2 -3
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +15 -4
- data/lib/tasks/paperclip.rake +17 -1
- data/paperclip.gemspec +18 -15
- data/spec/paperclip/attachment_definitions_spec.rb +1 -1
- data/spec/paperclip/attachment_processing_spec.rb +2 -4
- data/spec/paperclip/attachment_registry_spec.rb +84 -13
- data/spec/paperclip/attachment_spec.rb +91 -31
- data/spec/paperclip/content_type_detector_spec.rb +8 -1
- data/spec/paperclip/file_command_content_type_detector_spec.rb +0 -1
- data/spec/paperclip/geometry_spec.rb +1 -1
- data/spec/paperclip/glue_spec.rb +44 -0
- data/spec/paperclip/has_attached_file_spec.rb +24 -8
- data/spec/paperclip/integration_spec.rb +4 -3
- data/spec/paperclip/interpolations_spec.rb +16 -13
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +2 -1
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +4 -1
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +12 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +4 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +27 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +34 -11
- data/spec/paperclip/paperclip_spec.rb +4 -29
- data/spec/paperclip/plural_cache_spec.rb +17 -16
- data/spec/paperclip/rails_environment_spec.rb +33 -0
- data/spec/paperclip/storage/fog_spec.rb +42 -3
- data/spec/paperclip/storage/s3_live_spec.rb +8 -4
- data/spec/paperclip/storage/s3_spec.rb +255 -180
- data/spec/paperclip/tempfile_factory_spec.rb +4 -0
- data/spec/paperclip/thumbnail_spec.rb +16 -0
- data/spec/paperclip/url_generator_spec.rb +1 -1
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
- data/spec/paperclip/validators_spec.rb +3 -3
- data/spec/spec_helper.rb +6 -1
- data/spec/support/assertions.rb +7 -0
- data/spec/support/fake_model.rb +4 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/matchers/have_column.rb +11 -2
- data/spec/support/model_reconstruction.rb +9 -1
- data/spec/support/reporting.rb +11 -0
- metadata +105 -54
- data/RUNNING_TESTS.md +0 -4
- data/cucumber/paperclip_steps.rb +0 -6
- data/gemfiles/3.2.gemfile +0 -19
- data/gemfiles/4.0.gemfile +0 -19
- data/lib/paperclip/locales/de.yml +0 -18
- data/lib/paperclip/locales/es.yml +0 -18
- data/lib/paperclip/locales/ja.yml +0 -18
- data/lib/paperclip/locales/pt-BR.yml +0 -18
- data/lib/paperclip/locales/zh-CN.yml +0 -18
- data/lib/paperclip/locales/zh-HK.yml +0 -18
- data/lib/paperclip/locales/zh-TW.yml +0 -18
- data/spec/support/mock_model.rb +0 -2
- data/spec/support/rails_helpers.rb +0 -7
|
@@ -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:
|
|
35
|
-
[foo, :greeter, { ciao:
|
|
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:
|
|
54
|
-
greeter: { ciao:
|
|
53
|
+
avatar: { yo: "greeting" },
|
|
54
|
+
greeter: { ciao: "greeting" }
|
|
55
55
|
}
|
|
56
56
|
foo = Class.new
|
|
57
|
-
Paperclip::AttachmentRegistry.register(
|
|
58
|
-
|
|
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
|
|
66
|
-
expected_definitions = { avatar: { yo:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Paperclip::AttachmentRegistry.register(
|
|
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
|
-
|
|
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(
|
|
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:
|
|
38
|
-
large:
|
|
39
|
-
original:
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -635,15 +646,40 @@ describe Paperclip::Attachment do
|
|
|
635
646
|
before do
|
|
636
647
|
rebuild_model processor: [:thumbnail], styles: { small: '' }, whiny_thumbnails: true
|
|
637
648
|
@dummy = Dummy.new
|
|
638
|
-
Paperclip::Thumbnail.expects(:make).raises(Paperclip::Error, "cannot be processed.")
|
|
639
649
|
@file = StringIO.new("...")
|
|
640
650
|
@file.stubs(:to_tempfile).returns(@file)
|
|
641
|
-
@dummy.avatar = @file
|
|
642
651
|
end
|
|
643
652
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
653
|
+
context "when error is meaningful for the end user" do
|
|
654
|
+
before do
|
|
655
|
+
Paperclip::Thumbnail.expects(:make).raises(
|
|
656
|
+
Paperclip::Errors::NotIdentifiedByImageMagickError,
|
|
657
|
+
"cannot be processed."
|
|
658
|
+
)
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
it "correctly forwards processing error message to the instance" do
|
|
662
|
+
@dummy.avatar = @file
|
|
663
|
+
@dummy.valid?
|
|
664
|
+
assert_contains(
|
|
665
|
+
@dummy.errors.full_messages,
|
|
666
|
+
"Avatar cannot be processed."
|
|
667
|
+
)
|
|
668
|
+
end
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
context "when error is intended for the developer" do
|
|
672
|
+
before do
|
|
673
|
+
Paperclip::Thumbnail.expects(:make).raises(
|
|
674
|
+
Paperclip::Errors::CommandNotFoundError
|
|
675
|
+
)
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
it "propagates the error" do
|
|
679
|
+
assert_raises(Paperclip::Errors::CommandNotFoundError) do
|
|
680
|
+
@dummy.avatar = @file
|
|
681
|
+
end
|
|
682
|
+
end
|
|
647
683
|
end
|
|
648
684
|
end
|
|
649
685
|
|
|
@@ -661,9 +697,6 @@ describe Paperclip::Attachment do
|
|
|
661
697
|
|
|
662
698
|
context "when assigned" do
|
|
663
699
|
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
700
|
@dummy.avatar = @file
|
|
668
701
|
|
|
669
702
|
expect(Paperclip::Thumbnail).to have_received(:make)
|
|
@@ -678,7 +711,6 @@ describe Paperclip::Attachment do
|
|
|
678
711
|
convert_options: "",
|
|
679
712
|
source_file_options: ""
|
|
680
713
|
})
|
|
681
|
-
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
|
682
714
|
|
|
683
715
|
@dummy.avatar = @file
|
|
684
716
|
|
|
@@ -686,12 +718,36 @@ describe Paperclip::Attachment do
|
|
|
686
718
|
end
|
|
687
719
|
|
|
688
720
|
it "calls #make with attachment passed as third argument" do
|
|
689
|
-
Paperclip::Test.expects(:make).returns(@file)
|
|
690
|
-
|
|
691
721
|
@dummy.avatar = @file
|
|
692
722
|
|
|
693
723
|
expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
|
|
694
724
|
end
|
|
725
|
+
|
|
726
|
+
it "calls #make and unlinks intermediary files afterward" do
|
|
727
|
+
@dummy.avatar.expects(:unlink_files).with([@file, @file])
|
|
728
|
+
|
|
729
|
+
@dummy.avatar = @file
|
|
730
|
+
end
|
|
731
|
+
end
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
context "An attachment with a processor that returns original file" do
|
|
735
|
+
before do
|
|
736
|
+
class Paperclip::Test < Paperclip::Processor
|
|
737
|
+
def make; @file; end
|
|
738
|
+
end
|
|
739
|
+
rebuild_model processors: [:test], styles: { once: "100x100" }
|
|
740
|
+
@file = StringIO.new("...")
|
|
741
|
+
@file.stubs(:close)
|
|
742
|
+
@dummy = Dummy.new
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
context "when assigned" do
|
|
746
|
+
it "#calls #make and doesn't unlink the original file" do
|
|
747
|
+
@dummy.avatar.expects(:unlink_files).with([])
|
|
748
|
+
|
|
749
|
+
@dummy.avatar = @file
|
|
750
|
+
end
|
|
695
751
|
end
|
|
696
752
|
end
|
|
697
753
|
|
|
@@ -1065,7 +1121,7 @@ describe Paperclip::Attachment do
|
|
|
1065
1121
|
context "with a file assigned but not saved yet" do
|
|
1066
1122
|
it "clears out any attached files" do
|
|
1067
1123
|
@attachment.assign(@file)
|
|
1068
|
-
assert
|
|
1124
|
+
assert @attachment.queued_for_write.present?
|
|
1069
1125
|
@attachment.clear
|
|
1070
1126
|
assert @attachment.queued_for_write.blank?
|
|
1071
1127
|
end
|
|
@@ -1315,6 +1371,12 @@ describe Paperclip::Attachment do
|
|
|
1315
1371
|
end
|
|
1316
1372
|
|
|
1317
1373
|
it "does not calculate fingerprint" do
|
|
1374
|
+
Digest::MD5.stubs(:file)
|
|
1375
|
+
@dummy.avatar = @file
|
|
1376
|
+
expect(Digest::MD5).to have_received(:file).never
|
|
1377
|
+
end
|
|
1378
|
+
|
|
1379
|
+
it "does not assign fingerprint" do
|
|
1318
1380
|
@dummy.avatar = @file
|
|
1319
1381
|
assert_nil @dummy.avatar.fingerprint
|
|
1320
1382
|
end
|
|
@@ -1452,6 +1514,4 @@ describe Paperclip::Attachment do
|
|
|
1452
1514
|
assert_file_exists(@path)
|
|
1453
1515
|
end
|
|
1454
1516
|
end
|
|
1455
|
-
|
|
1456
1517
|
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.
|
|
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
|
|
@@ -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
|
|
@@ -38,6 +38,15 @@ describe Paperclip::HasAttachedFile do
|
|
|
38
38
|
assert_adding_attachment('avatar').defines_callback('after_commit')
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
context 'when the class does not allow after_commit callbacks' do
|
|
42
|
+
it 'defines an after_destroy callback' do
|
|
43
|
+
assert_adding_attachment(
|
|
44
|
+
'avatar',
|
|
45
|
+
unstub_methods: [:after_commit]
|
|
46
|
+
).defines_callback('after_destroy')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
it 'defines the Paperclip-specific callbacks' do
|
|
42
51
|
assert_adding_attachment('avatar').defines_callback('define_paperclip_callbacks')
|
|
43
52
|
end
|
|
@@ -53,20 +62,26 @@ describe Paperclip::HasAttachedFile do
|
|
|
53
62
|
|
|
54
63
|
private
|
|
55
64
|
|
|
56
|
-
def assert_adding_attachment(attachment_name)
|
|
57
|
-
AttachmentAdder.new(attachment_name)
|
|
65
|
+
def assert_adding_attachment(attachment_name, options={})
|
|
66
|
+
AttachmentAdder.new(attachment_name, options)
|
|
58
67
|
end
|
|
59
68
|
|
|
60
69
|
class AttachmentAdder
|
|
61
70
|
include Mocha::API
|
|
62
71
|
include RSpec::Matchers
|
|
63
72
|
|
|
64
|
-
def initialize(attachment_name)
|
|
73
|
+
def initialize(attachment_name, options = {})
|
|
65
74
|
@attachment_name = attachment_name
|
|
75
|
+
@stubbed_class = stub_class
|
|
76
|
+
if options.present?
|
|
77
|
+
options[:unstub_methods].each do |method|
|
|
78
|
+
@stubbed_class.unstub(method)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
66
81
|
end
|
|
67
82
|
|
|
68
83
|
def defines_method(method_name)
|
|
69
|
-
a_class =
|
|
84
|
+
a_class = @stubbed_class
|
|
70
85
|
|
|
71
86
|
Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
|
|
72
87
|
|
|
@@ -74,7 +89,7 @@ describe Paperclip::HasAttachedFile do
|
|
|
74
89
|
end
|
|
75
90
|
|
|
76
91
|
def defines_class_method(method_name)
|
|
77
|
-
a_class =
|
|
92
|
+
a_class = @stubbed_class
|
|
78
93
|
a_class.class.stubs(:define_method)
|
|
79
94
|
|
|
80
95
|
Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
|
|
@@ -83,7 +98,7 @@ describe Paperclip::HasAttachedFile do
|
|
|
83
98
|
end
|
|
84
99
|
|
|
85
100
|
def defines_validation
|
|
86
|
-
a_class =
|
|
101
|
+
a_class = @stubbed_class
|
|
87
102
|
|
|
88
103
|
Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
|
|
89
104
|
|
|
@@ -91,7 +106,7 @@ describe Paperclip::HasAttachedFile do
|
|
|
91
106
|
end
|
|
92
107
|
|
|
93
108
|
def registers_attachment
|
|
94
|
-
a_class =
|
|
109
|
+
a_class = @stubbed_class
|
|
95
110
|
Paperclip::AttachmentRegistry.stubs(:register)
|
|
96
111
|
|
|
97
112
|
Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {size: 1})
|
|
@@ -100,7 +115,7 @@ describe Paperclip::HasAttachedFile do
|
|
|
100
115
|
end
|
|
101
116
|
|
|
102
117
|
def defines_callback(callback_name)
|
|
103
|
-
a_class =
|
|
118
|
+
a_class = @stubbed_class
|
|
104
119
|
|
|
105
120
|
Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
|
|
106
121
|
|
|
@@ -132,6 +147,7 @@ describe Paperclip::HasAttachedFile do
|
|
|
132
147
|
after_save: nil,
|
|
133
148
|
before_destroy: nil,
|
|
134
149
|
after_commit: nil,
|
|
150
|
+
after_destroy: nil,
|
|
135
151
|
define_paperclip_callbacks: nil,
|
|
136
152
|
extend: nil,
|
|
137
153
|
name: 'Billy',
|
|
@@ -7,9 +7,10 @@ describe 'Paperclip' do
|
|
|
7
7
|
before do
|
|
8
8
|
rebuild_model
|
|
9
9
|
@file = File.new(fixture_file("5k.png"), 'rb')
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
# Deals with `Too many open files` error
|
|
11
|
+
Dummy.import 100.times.map { Dummy.new avatar: @file }
|
|
12
|
+
Dummy.import 100.times.map { Dummy.new avatar: @file }
|
|
13
|
+
Dummy.import 100.times.map { Dummy.new avatar: @file }
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
after { @file.close }
|
|
@@ -24,15 +24,16 @@ describe Paperclip::Interpolations do
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it "returns the class of the instance" do
|
|
27
|
+
class Thing ; end
|
|
27
28
|
attachment = mock
|
|
28
29
|
attachment.expects(:instance).returns(attachment)
|
|
29
|
-
attachment.expects(:class).returns(
|
|
30
|
+
attachment.expects(:class).returns(Thing)
|
|
30
31
|
assert_equal "things", Paperclip::Interpolations.class(attachment, :style)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
it "returns the basename of the file" do
|
|
34
35
|
attachment = mock
|
|
35
|
-
attachment.expects(:original_filename).returns("one.jpg").times(
|
|
36
|
+
attachment.expects(:original_filename).returns("one.jpg").times(1)
|
|
36
37
|
assert_equal "one", Paperclip::Interpolations.basename(attachment, :style)
|
|
37
38
|
end
|
|
38
39
|
|
|
@@ -138,14 +139,7 @@ describe Paperclip::Interpolations do
|
|
|
138
139
|
assert_equal "000/000/023", Paperclip::Interpolations.id_partition(attachment, :style)
|
|
139
140
|
end
|
|
140
141
|
|
|
141
|
-
it "returns the partitioned id of the attachment when the id is a
|
|
142
|
-
attachment = mock
|
|
143
|
-
attachment.expects(:id).returns("fnj23")
|
|
144
|
-
attachment.expects(:instance).returns(attachment)
|
|
145
|
-
assert_equal "000/0fn/j23", Paperclip::Interpolations.id_partition(attachment, :style)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
it "returns the partitioned id of the attachment when the id is a long string" do
|
|
142
|
+
it "returns the partitioned id of the attachment when the id is a string" do
|
|
149
143
|
attachment = mock
|
|
150
144
|
attachment.expects(:id).returns("32fnj23oio2f")
|
|
151
145
|
attachment.expects(:instance).returns(attachment)
|
|
@@ -194,14 +188,14 @@ describe Paperclip::Interpolations do
|
|
|
194
188
|
it "returns the filename as basename.extension" do
|
|
195
189
|
attachment = mock
|
|
196
190
|
attachment.expects(:styles).returns({})
|
|
197
|
-
attachment.expects(:original_filename).returns("one.jpg").times(
|
|
191
|
+
attachment.expects(:original_filename).returns("one.jpg").times(2)
|
|
198
192
|
assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
|
|
199
193
|
end
|
|
200
194
|
|
|
201
195
|
it "returns the filename as basename.extension when format supplied" do
|
|
202
196
|
attachment = mock
|
|
203
197
|
attachment.expects(:styles).returns({style: {format: :png}})
|
|
204
|
-
attachment.expects(:original_filename).returns("one.jpg").times(
|
|
198
|
+
attachment.expects(:original_filename).returns("one.jpg").times(1)
|
|
205
199
|
assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
|
|
206
200
|
end
|
|
207
201
|
|
|
@@ -211,7 +205,7 @@ describe Paperclip::Interpolations do
|
|
|
211
205
|
attachment.stubs(:original_filename).returns("one")
|
|
212
206
|
assert_equal "one", Paperclip::Interpolations.filename(attachment, :style)
|
|
213
207
|
end
|
|
214
|
-
|
|
208
|
+
|
|
215
209
|
it "returns the basename when the extension contains regexp special characters" do
|
|
216
210
|
attachment = mock
|
|
217
211
|
attachment.stubs(:styles).returns({})
|
|
@@ -256,4 +250,13 @@ describe Paperclip::Interpolations do
|
|
|
256
250
|
value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
|
|
257
251
|
assert_equal ":notreal/1234/attachments", value
|
|
258
252
|
end
|
|
253
|
+
|
|
254
|
+
it "handles question marks" do
|
|
255
|
+
Paperclip.interpolates :foo? do
|
|
256
|
+
"bar"
|
|
257
|
+
end
|
|
258
|
+
Paperclip::Interpolations.expects(:fool).never
|
|
259
|
+
value = Paperclip::Interpolations.interpolate(":fo/:foo?")
|
|
260
|
+
assert_equal ":fo/bar", value
|
|
261
|
+
end
|
|
259
262
|
end
|
|
@@ -9,11 +9,12 @@ describe Paperclip::AbstractAdapter do
|
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
context "content type from file
|
|
12
|
+
context "content type from file contents" do
|
|
13
13
|
before do
|
|
14
14
|
@adapter = TestAdapter.new
|
|
15
15
|
@adapter.stubs(:path).returns("image.png")
|
|
16
16
|
Paperclip.stubs(:run).returns("image/png\n")
|
|
17
|
+
Paperclip::ContentTypeDetector.any_instance.stubs(:type_from_mime_magic).returns("image/png")
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
it "returns the content type without newline" do
|