kt-paperclip 4.4.0 → 5.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +17 -0
- data/.hound.yml +5 -16
- data/.travis.yml +15 -12
- data/Appraisals +4 -8
- data/CONTRIBUTING.md +16 -5
- data/Gemfile +3 -8
- data/LICENSE +1 -1
- data/NEWS +105 -31
- data/README.md +239 -153
- data/Rakefile +1 -1
- data/UPGRADING +12 -9
- data/features/basic_integration.feature +3 -2
- data/features/migration.feature +0 -24
- data/features/step_definitions/attachment_steps.rb +6 -6
- data/features/step_definitions/rails_steps.rb +29 -28
- data/features/step_definitions/s3_steps.rb +2 -2
- data/features/support/env.rb +1 -0
- data/features/support/paths.rb +1 -1
- data/features/support/rails.rb +0 -24
- data/gemfiles/4.2.gemfile +3 -5
- data/gemfiles/{3.2.gemfile → 5.0.gemfile} +4 -6
- data/lib/generators/paperclip/paperclip_generator.rb +9 -1
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip/attachment.rb +25 -14
- data/lib/paperclip/attachment_registry.rb +2 -1
- data/lib/paperclip/callbacks.rb +8 -6
- data/lib/paperclip/content_type_detector.rb +3 -2
- data/lib/paperclip/errors.rb +3 -1
- data/lib/paperclip/file_command_content_type_detector.rb +1 -1
- data/lib/paperclip/geometry_detector_factory.rb +2 -2
- data/lib/paperclip/glue.rb +1 -1
- data/lib/paperclip/has_attached_file.rb +7 -1
- data/lib/paperclip/helpers.rb +15 -11
- data/lib/paperclip/interpolations.rb +1 -1
- data/lib/paperclip/io_adapters/abstract_adapter.rb +29 -3
- data/lib/paperclip/io_adapters/attachment_adapter.rb +10 -5
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +8 -8
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
- data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +7 -7
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
- data/lib/paperclip/io_adapters/registry.rb +6 -2
- data/lib/paperclip/io_adapters/stringio_adapter.rb +9 -6
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
- data/lib/paperclip/io_adapters/uri_adapter.rb +17 -14
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +3 -2
- data/lib/paperclip/processor.rb +5 -4
- data/lib/paperclip/schema.rb +4 -10
- data/lib/paperclip/storage/filesystem.rb +13 -2
- data/lib/paperclip/storage/fog.rb +19 -13
- data/lib/paperclip/storage/s3.rb +87 -58
- data/lib/paperclip/thumbnail.rb +18 -8
- data/lib/paperclip/url_generator.rb +18 -14
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/validators.rb +1 -1
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +13 -12
- data/lib/tasks/paperclip.rake +18 -4
- data/paperclip.gemspec +13 -11
- data/spec/paperclip/attachment_processing_spec.rb +2 -4
- data/spec/paperclip/attachment_registry_spec.rb +28 -0
- data/spec/paperclip/attachment_spec.rb +72 -18
- data/spec/paperclip/content_type_detector_spec.rb +1 -1
- data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -1
- data/spec/paperclip/has_attached_file_spec.rb +24 -8
- data/spec/paperclip/integration_spec.rb +4 -3
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +76 -22
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +6 -3
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +7 -1
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +2 -2
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +18 -1
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/registry_spec.rb +2 -2
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +5 -5
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +48 -3
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +15 -0
- data/spec/paperclip/paperclip_spec.rb +15 -45
- data/spec/paperclip/processor_spec.rb +4 -4
- data/spec/paperclip/storage/fog_spec.rb +26 -0
- data/spec/paperclip/storage/s3_live_spec.rb +20 -14
- data/spec/paperclip/storage/s3_spec.rb +357 -190
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +38 -35
- data/spec/paperclip/url_generator_spec.rb +53 -42
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
- data/spec/paperclip/validators_spec.rb +5 -5
- data/spec/spec_helper.rb +6 -2
- data/spec/support/assertions.rb +12 -1
- data/spec/support/conditional_filter_helper.rb +5 -0
- data/spec/support/mock_attachment.rb +2 -0
- data/spec/support/mock_url_generator_builder.rb +2 -2
- data/spec/support/model_reconstruction.rb +10 -2
- data/spec/support/reporting.rb +11 -0
- metadata +69 -75
- data/cucumber/paperclip_steps.rb +0 -6
- data/gemfiles/4.1.gemfile +0 -19
- data/lib/paperclip/deprecations.rb +0 -42
- 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/paperclip/deprecations_spec.rb +0 -65
- data/spec/support/deprecations.rb +0 -9
- data/spec/support/rails_helpers.rb +0 -7
data/lib/tasks/paperclip.rake
CHANGED
@@ -18,7 +18,7 @@ module Paperclip
|
|
18
18
|
raise "Class #{klass.name} has no attachments specified"
|
19
19
|
end
|
20
20
|
|
21
|
-
if
|
21
|
+
if name.present? && attachment_names.map(&:to_s).include?(name.to_s)
|
22
22
|
[ name ]
|
23
23
|
else
|
24
24
|
attachment_names
|
@@ -46,7 +46,7 @@ namespace :paperclip do
|
|
46
46
|
attachment = instance.send(name)
|
47
47
|
begin
|
48
48
|
attachment.reprocess!(*styles)
|
49
|
-
rescue
|
49
|
+
rescue StandardError => e
|
50
50
|
Paperclip::Task.log_error("exception while processing #{klass} ID #{instance.id}:")
|
51
51
|
Paperclip::Task.log_error(" " + e.message + "\n")
|
52
52
|
end
|
@@ -64,7 +64,8 @@ namespace :paperclip do
|
|
64
64
|
names = Paperclip::Task.obtain_attachments(klass)
|
65
65
|
names.each do |name|
|
66
66
|
Paperclip.each_instance_with_attachment(klass, name) do |instance|
|
67
|
-
|
67
|
+
attachment = instance.send(name)
|
68
|
+
if file = Paperclip.io_adapters.for(attachment, attachment.options[:adapter_options])
|
68
69
|
instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
|
69
70
|
instance.send("#{name}_content_type=", file.content_type.to_s.strip)
|
70
71
|
instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
|
@@ -90,6 +91,19 @@ namespace :paperclip do
|
|
90
91
|
end
|
91
92
|
Paperclip.save_current_attachments_styles!
|
92
93
|
end
|
94
|
+
|
95
|
+
desc "Regenerates fingerprints for a given CLASS (and optional ATTACHMENT). Useful when changing digest."
|
96
|
+
task :fingerprints => :environment do
|
97
|
+
klass = Paperclip::Task.obtain_class
|
98
|
+
names = Paperclip::Task.obtain_attachments(klass)
|
99
|
+
names.each do |name|
|
100
|
+
Paperclip.each_instance_with_attachment(klass, name) do |instance|
|
101
|
+
attachment = instance.send(name)
|
102
|
+
attachment.assign(attachment)
|
103
|
+
instance.save(:validate => false)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
93
107
|
end
|
94
108
|
|
95
109
|
desc "Cleans out invalid attachments. Useful after you've added new validations."
|
@@ -109,7 +123,7 @@ namespace :paperclip do
|
|
109
123
|
end
|
110
124
|
end
|
111
125
|
|
112
|
-
|
126
|
+
desc "find missing attachments. Useful to know which attachments are broken"
|
113
127
|
task :find_broken_attachments => :environment do
|
114
128
|
klass = Paperclip::Task.obtain_class
|
115
129
|
names = Paperclip::Task.obtain_attachments(klass)
|
data/paperclip.gemspec
CHANGED
@@ -17,27 +17,30 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
+
if File.exist?('UPGRADING')
|
21
|
+
s.post_install_message = File.read("UPGRADING")
|
22
|
+
end
|
23
|
+
|
20
24
|
s.requirements << "ImageMagick"
|
21
|
-
s.required_ruby_version = ">= 1.
|
25
|
+
s.required_ruby_version = ">= 2.1.0"
|
22
26
|
|
23
|
-
s.add_dependency('activemodel', '>=
|
24
|
-
s.add_dependency('activesupport', '>=
|
25
|
-
s.add_dependency('
|
27
|
+
s.add_dependency('activemodel', '>= 4.2.0', '< 6.0')
|
28
|
+
s.add_dependency('activesupport', '>= 4.2.0', '< 6.0')
|
29
|
+
s.add_dependency('terrapin', '~> 0.6.0')
|
26
30
|
s.add_dependency('mime-types')
|
27
31
|
s.add_dependency('mimemagic', '~> 0.3.8')
|
28
|
-
s.add_dependency('bigdecimal', '1.3.5')
|
29
32
|
|
30
|
-
s.add_development_dependency('activerecord', '>=
|
33
|
+
s.add_development_dependency('activerecord', '>= 4.2.0', '< 6.0')
|
31
34
|
s.add_development_dependency('shoulda')
|
32
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', '>=
|
38
|
+
s.add_development_dependency('aws-sdk', '>= 2.3.0', '< 3.0')
|
36
39
|
s.add_development_dependency('bourne', '< 1.6')
|
37
|
-
s.add_development_dependency('cucumber'
|
40
|
+
s.add_development_dependency('cucumber-rails')
|
41
|
+
s.add_development_dependency('cucumber-expressions', '4.0.3') # TODO: investigate failures on 4.0.4
|
38
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
44
|
s.add_development_dependency('capybara')
|
42
45
|
s.add_development_dependency('bundler')
|
43
46
|
s.add_development_dependency('fog-aws')
|
@@ -45,8 +48,7 @@ Gem::Specification.new do |s|
|
|
45
48
|
s.add_development_dependency('launchy')
|
46
49
|
s.add_development_dependency('rake')
|
47
50
|
s.add_development_dependency('fakeweb')
|
48
|
-
s.add_development_dependency('railties')
|
49
|
-
s.add_development_dependency('actionmailer', '>= 3.2.0', '< 5.0')
|
51
|
+
s.add_development_dependency('railties', '>= 4.2.0', '< 6.0')
|
50
52
|
s.add_development_dependency('generator_spec')
|
51
53
|
s.add_development_dependency('timecop')
|
52
54
|
end
|
@@ -2,11 +2,9 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe 'Attachment Processing' do
|
5
|
-
|
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"
|
@@ -111,6 +111,34 @@ describe 'Attachment Registry' do
|
|
111
111
|
|
112
112
|
assert_equal expected_definitions, definitions
|
113
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)
|
139
|
+
|
140
|
+
assert_equal expected_definitions, definitions
|
141
|
+
end
|
114
142
|
end
|
115
143
|
|
116
144
|
context '.clear' do
|
@@ -222,9 +222,6 @@ describe Paperclip::Attachment do
|
|
222
222
|
dummy.avatar_file_name = "fake.jpg"
|
223
223
|
dummy.stubs(:new_record?).returns(false)
|
224
224
|
expected_string = '{"avatar":"/system/dummies/avatars/000/001/234/original/fake.jpg"}'
|
225
|
-
if ActiveRecord::Base.include_root_in_json # This is true by default in Rails 3, and false in 4
|
226
|
-
expected_string = %({"dummy":#{expected_string}})
|
227
|
-
end
|
228
225
|
# active_model pre-3.2 checks only by calling any? on it, thus it doesn't work if it is empty
|
229
226
|
assert_equal expected_string, dummy.to_json(only: [:dummy_key_for_old_active_model], methods: [:avatar])
|
230
227
|
end
|
@@ -503,6 +500,7 @@ describe Paperclip::Attachment do
|
|
503
500
|
@attachment.expects(:post_process).with(:thumb)
|
504
501
|
@attachment.expects(:post_process).with(:large).never
|
505
502
|
@attachment.assign(@file)
|
503
|
+
@attachment.save
|
506
504
|
end
|
507
505
|
end
|
508
506
|
|
@@ -700,9 +698,6 @@ describe Paperclip::Attachment do
|
|
700
698
|
|
701
699
|
context "when assigned" do
|
702
700
|
it "calls #make on all specified processors" do
|
703
|
-
Paperclip::Thumbnail.stubs(:make).with(any_parameters).returns(@file)
|
704
|
-
Paperclip::Test.stubs(:make).with(any_parameters).returns(@file)
|
705
|
-
|
706
701
|
@dummy.avatar = @file
|
707
702
|
|
708
703
|
expect(Paperclip::Thumbnail).to have_received(:make)
|
@@ -717,7 +712,6 @@ describe Paperclip::Attachment do
|
|
717
712
|
convert_options: "",
|
718
713
|
source_file_options: ""
|
719
714
|
})
|
720
|
-
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
721
715
|
|
722
716
|
@dummy.avatar = @file
|
723
717
|
|
@@ -725,12 +719,36 @@ describe Paperclip::Attachment do
|
|
725
719
|
end
|
726
720
|
|
727
721
|
it "calls #make with attachment passed as third argument" do
|
728
|
-
Paperclip::Test.expects(:make).returns(@file)
|
729
|
-
|
730
722
|
@dummy.avatar = @file
|
731
723
|
|
732
724
|
expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
|
733
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
|
734
752
|
end
|
735
753
|
end
|
736
754
|
|
@@ -1104,7 +1122,7 @@ describe Paperclip::Attachment do
|
|
1104
1122
|
context "with a file assigned but not saved yet" do
|
1105
1123
|
it "clears out any attached files" do
|
1106
1124
|
@attachment.assign(@file)
|
1107
|
-
assert
|
1125
|
+
assert @attachment.queued_for_write.present?
|
1108
1126
|
@attachment.clear
|
1109
1127
|
assert @attachment.queued_for_write.blank?
|
1110
1128
|
end
|
@@ -1354,6 +1372,12 @@ describe Paperclip::Attachment do
|
|
1354
1372
|
end
|
1355
1373
|
|
1356
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
|
1357
1381
|
@dummy.avatar = @file
|
1358
1382
|
assert_nil @dummy.avatar.fingerprint
|
1359
1383
|
end
|
@@ -1410,16 +1434,46 @@ describe Paperclip::Attachment do
|
|
1410
1434
|
assert_nothing_raised { @dummy.avatar = @file }
|
1411
1435
|
end
|
1412
1436
|
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
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
|
1416
1456
|
end
|
1417
1457
|
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
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
|
1423
1477
|
end
|
1424
1478
|
end
|
1425
1479
|
end
|
@@ -41,7 +41,7 @@ describe Paperclip::ContentTypeDetector do
|
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'returns a sensible default when the file command is missing' do
|
44
|
-
Paperclip.stubs(:run).raises(
|
44
|
+
Paperclip.stubs(:run).raises(Terrapin::CommandLineError.new)
|
45
45
|
@filename = "/path/to/something"
|
46
46
|
assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new(@filename).detect
|
47
47
|
end
|
@@ -12,7 +12,7 @@ describe Paperclip::FileCommandContentTypeDetector do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'returns a sensible default when the file command is missing' do
|
15
|
-
Paperclip.stubs(:run).raises(
|
15
|
+
Paperclip.stubs(:run).raises(Terrapin::CommandLineError.new)
|
16
16
|
@filename = "/path/to/something"
|
17
17
|
assert_equal "application/octet-stream",
|
18
18
|
Paperclip::FileCommandContentTypeDetector.new(@filename).detect
|
@@ -23,4 +23,18 @@ describe Paperclip::FileCommandContentTypeDetector do
|
|
23
23
|
assert_equal "application/octet-stream",
|
24
24
|
Paperclip::FileCommandContentTypeDetector.new("windows").detect
|
25
25
|
end
|
26
|
+
|
27
|
+
context "#type_from_file_command" do
|
28
|
+
let(:detector) { Paperclip::FileCommandContentTypeDetector.new("html") }
|
29
|
+
|
30
|
+
it "does work with the output of old versions of file" do
|
31
|
+
Paperclip.stubs(:run).returns("text/html charset=us-ascii")
|
32
|
+
expect(detector.detect).to eq("text/html")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "does work with the output of new versions of file" do
|
36
|
+
Paperclip.stubs(:run).returns("text/html; charset=us-ascii")
|
37
|
+
expect(detector.detect).to eq("text/html")
|
38
|
+
end
|
39
|
+
end
|
26
40
|
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 }
|
@@ -9,70 +9,124 @@ describe Paperclip::AbstractAdapter do
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
subject { TestAdapter.new(nil) }
|
13
|
+
|
12
14
|
context "content type from file contents" do
|
13
15
|
before do
|
14
|
-
|
15
|
-
@adapter.stubs(:path).returns("image.png")
|
16
|
+
subject.stubs(:path).returns("image.png")
|
16
17
|
Paperclip.stubs(:run).returns("image/png\n")
|
17
18
|
Paperclip::ContentTypeDetector.any_instance.stubs(:type_from_mime_magic).returns("image/png")
|
18
19
|
end
|
19
20
|
|
20
21
|
it "returns the content type without newline" do
|
21
|
-
assert_equal "image/png",
|
22
|
+
assert_equal "image/png", subject.content_type
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
26
|
context "nil?" do
|
26
27
|
it "returns false" do
|
27
|
-
assert !
|
28
|
+
assert !subject.nil?
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
32
|
context "delegation" do
|
32
33
|
before do
|
33
|
-
|
34
|
-
@adapter.tempfile = stub("Tempfile")
|
34
|
+
subject.tempfile = stub("Tempfile")
|
35
35
|
end
|
36
36
|
|
37
|
-
[:binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :rewind, :unlink].each do |method|
|
37
|
+
[:binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink].each do |method|
|
38
38
|
it "delegates #{method} to @tempfile" do
|
39
|
-
|
40
|
-
|
41
|
-
assert_received
|
39
|
+
subject.tempfile.stubs(method)
|
40
|
+
subject.public_send(method)
|
41
|
+
assert_received subject.tempfile, method
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
it 'gets rid of slashes and colons in filenames' do
|
47
|
-
|
48
|
-
@adapter.original_filename = "awesome/file:name.png"
|
47
|
+
subject.original_filename = "awesome/file:name.png"
|
49
48
|
|
50
|
-
assert_equal "awesome_file_name.png",
|
49
|
+
assert_equal "awesome_file_name.png", subject.original_filename
|
51
50
|
end
|
52
51
|
|
53
52
|
it 'is an assignment' do
|
54
|
-
assert
|
53
|
+
assert subject.assignment?
|
55
54
|
end
|
56
55
|
|
57
56
|
it 'is not nil' do
|
58
|
-
assert !
|
57
|
+
assert !subject.nil?
|
59
58
|
end
|
60
59
|
|
61
60
|
it "generates a destination filename with no original filename" do
|
62
|
-
|
63
|
-
expect(@adapter.send(:destination).path).to_not be_nil
|
61
|
+
expect(subject.send(:destination).path).to_not be_nil
|
64
62
|
end
|
65
63
|
|
66
64
|
it 'uses the original filename to generate the tempfile' do
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
subject.original_filename = "file.png"
|
66
|
+
expect(subject.send(:destination).path).to end_with(".png")
|
67
|
+
end
|
68
|
+
|
69
|
+
context "generates a fingerprint" do
|
70
|
+
subject { TestAdapter.new(nil, options) }
|
71
|
+
|
72
|
+
before do
|
73
|
+
subject.stubs(:path).returns(fixture_file("50x50.png"))
|
74
|
+
end
|
75
|
+
|
76
|
+
context "MD5" do
|
77
|
+
let(:options) { { hash_digest: Digest::MD5 } }
|
78
|
+
|
79
|
+
it "returns a fingerprint" do
|
80
|
+
expect(subject.fingerprint).to be_a String
|
81
|
+
expect(subject.fingerprint).to eq "a790b00c9b5d58a8fd17a1ec5a187129"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "SHA256" do
|
86
|
+
let(:options) { { hash_digest: Digest::SHA256 } }
|
87
|
+
|
88
|
+
it "returns a fingerprint" do
|
89
|
+
expect(subject.fingerprint).to be_a String
|
90
|
+
expect(subject.fingerprint).
|
91
|
+
to eq "243d7ce1099719df25f600f1c369c629fb979f88d5a01dbe7d0d48c8e6715bb1"
|
92
|
+
end
|
93
|
+
end
|
70
94
|
end
|
71
95
|
|
72
96
|
context "#original_filename=" do
|
73
97
|
it "should not fail with a nil original filename" do
|
74
|
-
|
75
|
-
|
98
|
+
expect { subject.original_filename = nil }.not_to raise_error
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "#link_or_copy_file" do
|
103
|
+
class TestLinkOrCopyAdapter < Paperclip::AbstractAdapter
|
104
|
+
public :copy_to_tempfile, :destination
|
105
|
+
end
|
106
|
+
|
107
|
+
subject { TestLinkOrCopyAdapter.new(nil) }
|
108
|
+
let(:body) { "body" }
|
109
|
+
|
110
|
+
let(:file) do
|
111
|
+
t = Tempfile.new("destination")
|
112
|
+
t.print(body)
|
113
|
+
t.rewind
|
114
|
+
t
|
115
|
+
end
|
116
|
+
|
117
|
+
after do
|
118
|
+
file.close
|
119
|
+
file.unlink
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should be able to read the file" do
|
123
|
+
expect(subject.copy_to_tempfile(file).read).to eq(body)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be able to reopen the file after symlink has failed" do
|
127
|
+
FileUtils.expects(:ln).raises(Errno::EXDEV)
|
128
|
+
|
129
|
+
expect(subject.copy_to_tempfile(file).read).to eq(body)
|
76
130
|
end
|
77
131
|
end
|
78
132
|
end
|
@@ -13,7 +13,8 @@ describe Paperclip::AttachmentAdapter do
|
|
13
13
|
|
14
14
|
@attachment.assign(@file)
|
15
15
|
@attachment.save
|
16
|
-
@subject = Paperclip.io_adapters.for(@attachment
|
16
|
+
@subject = Paperclip.io_adapters.for(@attachment,
|
17
|
+
hash_digest: Digest::MD5)
|
17
18
|
end
|
18
19
|
|
19
20
|
after do
|
@@ -65,7 +66,8 @@ describe Paperclip::AttachmentAdapter do
|
|
65
66
|
|
66
67
|
@attachment.assign(@file)
|
67
68
|
@attachment.save
|
68
|
-
@subject = Paperclip.io_adapters.for(@attachment
|
69
|
+
@subject = Paperclip.io_adapters.for(@attachment,
|
70
|
+
hash_digest: Digest::MD5)
|
69
71
|
end
|
70
72
|
|
71
73
|
after do
|
@@ -92,7 +94,8 @@ describe Paperclip::AttachmentAdapter do
|
|
92
94
|
FileUtils.cp @attachment.queued_for_write[:thumb].path, @thumb.path
|
93
95
|
|
94
96
|
@attachment.save
|
95
|
-
@subject = Paperclip.io_adapters.for(@attachment.styles[:thumb]
|
97
|
+
@subject = Paperclip.io_adapters.for(@attachment.styles[:thumb],
|
98
|
+
hash_digest: Digest::MD5)
|
96
99
|
end
|
97
100
|
|
98
101
|
after do
|
@@ -1,7 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Paperclip::DataUriAdapter do
|
4
|
+
before do
|
5
|
+
Paperclip::DataUriAdapter.register
|
6
|
+
end
|
7
|
+
|
4
8
|
after do
|
9
|
+
Paperclip.io_adapters.unregister(described_class)
|
10
|
+
|
5
11
|
if @subject
|
6
12
|
@subject.close
|
7
13
|
end
|
@@ -20,7 +26,7 @@ describe Paperclip::DataUriAdapter do
|
|
20
26
|
context "a new instance" do
|
21
27
|
before do
|
22
28
|
@contents = "data:image/png;base64,#{original_base64_content}"
|
23
|
-
@subject = Paperclip.io_adapters.for(@contents)
|
29
|
+
@subject = Paperclip.io_adapters.for(@contents, hash_digest: Digest::MD5)
|
24
30
|
end
|
25
31
|
|
26
32
|
it "returns a nondescript file name" do
|
@@ -15,7 +15,7 @@ describe Paperclip::FileAdapter do
|
|
15
15
|
|
16
16
|
context 'doing normal things' do
|
17
17
|
before do
|
18
|
-
@subject = Paperclip.io_adapters.for(@file)
|
18
|
+
@subject = Paperclip.io_adapters.for(@file, hash_digest: Digest::MD5)
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'uses the original filename to generate the tempfile' do
|
@@ -61,7 +61,7 @@ describe Paperclip::FileAdapter do
|
|
61
61
|
context "file with multiple possible content type" do
|
62
62
|
before do
|
63
63
|
MIME::Types.stubs(:type_for).returns([MIME::Type.new('image/x-png'), MIME::Type.new('image/png')])
|
64
|
-
@subject = Paperclip.io_adapters.for(@file)
|
64
|
+
@subject = Paperclip.io_adapters.for(@file, hash_digest: Digest::MD5)
|
65
65
|
end
|
66
66
|
|
67
67
|
it "prefers officially registered mime type" do
|