paperclip 4.3.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +14 -13
- data/Appraisals +22 -9
- data/CONTRIBUTING.md +16 -5
- data/Gemfile +2 -8
- data/LICENSE +1 -1
- data/NEWS +49 -2
- data/README.md +126 -102
- data/UPGRADING +12 -9
- data/features/basic_integration.feature +1 -0
- data/features/migration.feature +0 -24
- data/features/step_definitions/attachment_steps.rb +20 -20
- 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.2.gemfile → 4.2.awsv2.gemfile} +1 -1
- data/gemfiles/5.0.awsv2.0.gemfile +17 -0
- data/gemfiles/5.0.awsv2.1.gemfile +17 -0
- data/gemfiles/{4.1.gemfile → 5.0.awsv2.gemfile} +2 -2
- data/lib/paperclip/attachment.rb +18 -17
- 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/geometry_parser_factory.rb +1 -1
- data/lib/paperclip/glue.rb +1 -1
- data/lib/paperclip/has_attached_file.rb +7 -1
- 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/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 +1 -1
- data/lib/paperclip/rails_environment.rb +1 -1
- data/lib/paperclip/schema.rb +3 -9
- data/lib/paperclip/storage/fog.rb +17 -8
- data/lib/paperclip/storage/s3.rb +51 -49
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/version.rb +3 -1
- data/lib/paperclip.rb +2 -1
- data/lib/tasks/paperclip.rake +1 -1
- data/paperclip.gemspec +15 -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 +36 -14
- 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 +14 -4
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +12 -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 +12 -3
- data/spec/paperclip/paperclip_spec.rb +3 -28
- data/spec/paperclip/plural_cache_spec.rb +17 -16
- data/spec/paperclip/storage/fog_spec.rb +31 -1
- data/spec/paperclip/storage/s3_live_spec.rb +8 -4
- data/spec/paperclip/storage/s3_spec.rb +213 -156
- 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/model_reconstruction.rb +9 -1
- data/spec/support/reporting.rb +11 -0
- metadata +74 -47
- data/cucumber/paperclip_steps.rb +0 -6
- data/gemfiles/3.2.gemfile +0 -20
- 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/rails_helpers.rb +0 -7
data/lib/paperclip/version.rb
CHANGED
data/lib/paperclip.rb
CHANGED
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
|
data/paperclip.gemspec
CHANGED
@@ -17,34 +17,38 @@ 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', '>=
|
27
|
+
s.add_dependency('activemodel', '>= 4.2.0')
|
28
|
+
s.add_dependency('activesupport', '>= 4.2.0')
|
25
29
|
s.add_dependency('cocaine', '~> 0.5.5')
|
26
30
|
s.add_dependency('mime-types')
|
27
|
-
s.add_dependency('mimemagic', '0.3.0')
|
31
|
+
s.add_dependency('mimemagic', '~> 0.3.0')
|
28
32
|
|
29
|
-
s.add_development_dependency('activerecord', '>=
|
33
|
+
s.add_development_dependency('activerecord', '>= 4.2.0')
|
30
34
|
s.add_development_dependency('shoulda')
|
31
|
-
s.add_development_dependency('rspec')
|
35
|
+
s.add_development_dependency('rspec', '~> 3.0')
|
32
36
|
s.add_development_dependency('appraisal')
|
33
37
|
s.add_development_dependency('mocha')
|
34
|
-
s.add_development_dependency('aws-sdk', '>=
|
38
|
+
s.add_development_dependency('aws-sdk', '>= 2.0.34', '< 3.0')
|
35
39
|
s.add_development_dependency('bourne')
|
36
40
|
s.add_development_dependency('cucumber', '~> 1.3.18')
|
37
|
-
s.add_development_dependency('aruba')
|
41
|
+
s.add_development_dependency('aruba', '~> 0.9.0')
|
38
42
|
s.add_development_dependency('nokogiri')
|
39
|
-
# Ruby version < 1.9.3 can't install capybara > 2.0.3.
|
40
43
|
s.add_development_dependency('capybara')
|
41
44
|
s.add_development_dependency('bundler')
|
42
|
-
s.add_development_dependency('fog'
|
45
|
+
s.add_development_dependency('fog-aws')
|
46
|
+
s.add_development_dependency('fog-local')
|
43
47
|
s.add_development_dependency('launchy')
|
44
48
|
s.add_development_dependency('rake')
|
45
49
|
s.add_development_dependency('fakeweb')
|
46
50
|
s.add_development_dependency('railties')
|
47
|
-
s.add_development_dependency('actionmailer', '>=
|
51
|
+
s.add_development_dependency('actionmailer', '>= 4.2.0')
|
48
52
|
s.add_development_dependency('generator_spec')
|
49
53
|
s.add_development_dependency('timecop')
|
50
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
|
@@ -254,6 +251,7 @@ describe Paperclip::Attachment do
|
|
254
251
|
|
255
252
|
context "without an Attachment" do
|
256
253
|
before do
|
254
|
+
rebuild_model default_url: "default.url"
|
257
255
|
@dummy = Dummy.new
|
258
256
|
end
|
259
257
|
|
@@ -261,8 +259,8 @@ describe Paperclip::Attachment do
|
|
261
259
|
assert !@dummy.avatar.exists?
|
262
260
|
end
|
263
261
|
|
264
|
-
it "#url returns
|
265
|
-
|
262
|
+
it "#url returns the default_url" do
|
263
|
+
expect(@dummy.avatar.url).to eq "default.url"
|
266
264
|
end
|
267
265
|
end
|
268
266
|
|
@@ -699,9 +697,6 @@ describe Paperclip::Attachment do
|
|
699
697
|
|
700
698
|
context "when assigned" do
|
701
699
|
it "calls #make on all specified processors" do
|
702
|
-
Paperclip::Thumbnail.stubs(:make).with(any_parameters).returns(@file)
|
703
|
-
Paperclip::Test.stubs(:make).with(any_parameters).returns(@file)
|
704
|
-
|
705
700
|
@dummy.avatar = @file
|
706
701
|
|
707
702
|
expect(Paperclip::Thumbnail).to have_received(:make)
|
@@ -716,7 +711,6 @@ describe Paperclip::Attachment do
|
|
716
711
|
convert_options: "",
|
717
712
|
source_file_options: ""
|
718
713
|
})
|
719
|
-
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
720
714
|
|
721
715
|
@dummy.avatar = @file
|
722
716
|
|
@@ -724,12 +718,36 @@ describe Paperclip::Attachment do
|
|
724
718
|
end
|
725
719
|
|
726
720
|
it "calls #make with attachment passed as third argument" do
|
727
|
-
Paperclip::Test.expects(:make).returns(@file)
|
728
|
-
|
729
721
|
@dummy.avatar = @file
|
730
722
|
|
731
723
|
expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
|
732
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
|
733
751
|
end
|
734
752
|
end
|
735
753
|
|
@@ -1103,7 +1121,7 @@ describe Paperclip::Attachment do
|
|
1103
1121
|
context "with a file assigned but not saved yet" do
|
1104
1122
|
it "clears out any attached files" do
|
1105
1123
|
@attachment.assign(@file)
|
1106
|
-
assert
|
1124
|
+
assert @attachment.queued_for_write.present?
|
1107
1125
|
@attachment.clear
|
1108
1126
|
assert @attachment.queued_for_write.blank?
|
1109
1127
|
end
|
@@ -1353,6 +1371,12 @@ describe Paperclip::Attachment do
|
|
1353
1371
|
end
|
1354
1372
|
|
1355
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
|
1356
1380
|
@dummy.avatar = @file
|
1357
1381
|
assert_nil @dummy.avatar.fingerprint
|
1358
1382
|
end
|
@@ -1490,6 +1514,4 @@ describe Paperclip::Attachment do
|
|
1490
1514
|
assert_file_exists(@path)
|
1491
1515
|
end
|
1492
1516
|
end
|
1493
|
-
|
1494
1517
|
end
|
1495
|
-
|
@@ -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
|
|
@@ -187,14 +188,14 @@ describe Paperclip::Interpolations do
|
|
187
188
|
it "returns the filename as basename.extension" do
|
188
189
|
attachment = mock
|
189
190
|
attachment.expects(:styles).returns({})
|
190
|
-
attachment.expects(:original_filename).returns("one.jpg").times(
|
191
|
+
attachment.expects(:original_filename).returns("one.jpg").times(2)
|
191
192
|
assert_equal "one.jpg", Paperclip::Interpolations.filename(attachment, :style)
|
192
193
|
end
|
193
194
|
|
194
195
|
it "returns the filename as basename.extension when format supplied" do
|
195
196
|
attachment = mock
|
196
197
|
attachment.expects(:styles).returns({style: {format: :png}})
|
197
|
-
attachment.expects(:original_filename).returns("one.jpg").times(
|
198
|
+
attachment.expects(:original_filename).returns("one.jpg").times(1)
|
198
199
|
assert_equal "one.png", Paperclip::Interpolations.filename(attachment, :style)
|
199
200
|
end
|
200
201
|
|
@@ -249,4 +250,13 @@ describe Paperclip::Interpolations do
|
|
249
250
|
value = Paperclip::Interpolations.interpolate(":notreal/:id/:attachment", :attachment, :style)
|
250
251
|
assert_equal ":notreal/1234/attachments", value
|
251
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
|
252
262
|
end
|
@@ -98,4 +98,16 @@ describe Paperclip::HttpUrlProxyAdapter do
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
context "a url with special characters in the filename" do
|
102
|
+
it "returns a encoded filename" do
|
103
|
+
Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
|
104
|
+
returns(StringIO.new("x"))
|
105
|
+
url = "https://github.com/thoughtbot/paperclip-öäü字´½♥زÈ.png"
|
106
|
+
subject = Paperclip.io_adapters.for(url)
|
107
|
+
filename = "paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97%C2%B4%C2%BD%E2%99%A5"\
|
108
|
+
"%C3%98%C2%B2%C3%88.png"
|
109
|
+
|
110
|
+
assert_equal filename, subject.original_filename
|
111
|
+
end
|
112
|
+
end
|
101
113
|
end
|
@@ -99,4 +99,31 @@ describe Paperclip::UriAdapter do
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
+
describe "#download_content" do
|
103
|
+
before do
|
104
|
+
Paperclip::UriAdapter.any_instance.stubs(:open).returns(StringIO.new("xxx"))
|
105
|
+
@uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
|
106
|
+
@subject = Paperclip.io_adapters.for(@uri)
|
107
|
+
end
|
108
|
+
|
109
|
+
after do
|
110
|
+
@subject.send(:download_content)
|
111
|
+
end
|
112
|
+
|
113
|
+
context "with default read_timeout" do
|
114
|
+
it "calls open without options" do
|
115
|
+
@subject.expects(:open).with(@uri, {}).at_least_once
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with custom read_timeout" do
|
120
|
+
before do
|
121
|
+
Paperclip.options[:read_timeout] = 120
|
122
|
+
end
|
123
|
+
|
124
|
+
it "calls open with read_timeout option" do
|
125
|
+
@subject.expects(:open).with(@uri, read_timeout: 120).at_least_once
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
102
129
|
end
|
@@ -17,22 +17,26 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
17
17
|
|
18
18
|
it "rejects a class with no validation" do
|
19
19
|
expect(matcher).to_not accept(Dummy)
|
20
|
+
expect { matcher.failure_message }.to_not raise_error
|
20
21
|
end
|
21
22
|
|
22
23
|
it 'rejects a class when the validation fails' do
|
23
24
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
|
24
25
|
expect(matcher).to_not accept(Dummy)
|
26
|
+
expect { matcher.failure_message }.to_not raise_error
|
25
27
|
end
|
26
28
|
|
27
29
|
it "accepts a class with a matching validation" do
|
28
30
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
|
29
31
|
expect(matcher).to accept(Dummy)
|
32
|
+
expect { matcher.failure_message }.to_not raise_error
|
30
33
|
end
|
31
34
|
|
32
35
|
it "accepts a class with other validations but matching types" do
|
33
36
|
Dummy.validates_presence_of :title
|
34
37
|
Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
|
35
38
|
expect(matcher).to accept(Dummy)
|
39
|
+
expect { matcher.failure_message }.to_not raise_error
|
36
40
|
end
|
37
41
|
|
38
42
|
it "accepts a class that matches and a matcher that only specifies 'allowing'" do
|
@@ -40,6 +44,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
40
44
|
matcher = plain_matcher.allowing(%w(image/png image/jpeg))
|
41
45
|
|
42
46
|
expect(matcher).to accept(Dummy)
|
47
|
+
expect { matcher.failure_message }.to_not raise_error
|
43
48
|
end
|
44
49
|
|
45
50
|
it "rejects a class that does not match and a matcher that only specifies 'allowing'" do
|
@@ -47,6 +52,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
47
52
|
matcher = plain_matcher.allowing(%w(image/png image/jpeg))
|
48
53
|
|
49
54
|
expect(matcher).to_not accept(Dummy)
|
55
|
+
expect { matcher.failure_message }.to_not raise_error
|
50
56
|
end
|
51
57
|
|
52
58
|
it "accepts a class that matches and a matcher that only specifies 'rejecting'" do
|
@@ -54,6 +60,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
54
60
|
matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
|
55
61
|
|
56
62
|
expect(matcher).to accept(Dummy)
|
63
|
+
expect { matcher.failure_message }.to_not raise_error
|
57
64
|
end
|
58
65
|
|
59
66
|
it "rejects a class that does not match and a matcher that only specifies 'rejecting'" do
|
@@ -61,6 +68,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
61
68
|
matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
|
62
69
|
|
63
70
|
expect(matcher).to_not accept(Dummy)
|
71
|
+
expect { matcher.failure_message }.to_not raise_error
|
64
72
|
end
|
65
73
|
|
66
74
|
context "using an :if to control the validation" do
|
@@ -75,12 +83,14 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
|
|
75
83
|
dummy = Dummy.new
|
76
84
|
dummy.go = true
|
77
85
|
expect(matcher).to accept(dummy)
|
86
|
+
expect { matcher.failure_message }.to_not raise_error
|
78
87
|
end
|
79
88
|
|
80
89
|
it "does not run the validation if the control is false" do
|
81
90
|
dummy = Dummy.new
|
82
91
|
dummy.go = false
|
83
92
|
expect(matcher).to_not accept(dummy)
|
93
|
+
expect { matcher.failure_message }.to_not raise_error
|
84
94
|
end
|
85
95
|
end
|
86
96
|
|
@@ -44,9 +44,18 @@ describe Paperclip::MediaTypeSpoofDetector do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
file
|
49
|
-
|
47
|
+
context "file named .html and is as HTML, but we're told JPG" do
|
48
|
+
let(:file) { File.open(fixture_file("empty.html")) }
|
49
|
+
let(:spoofed?) { Paperclip::MediaTypeSpoofDetector.using(file, "empty.html", "image/jpg").spoofed? }
|
50
|
+
|
51
|
+
it "rejects the file" do
|
52
|
+
assert spoofed?
|
53
|
+
end
|
54
|
+
|
55
|
+
it "logs info about the detected spoof" do
|
56
|
+
Paperclip.expects(:log).with('Content Type Spoof: Filename empty.html (image/jpg from Headers, ["text/html"] from Extension), content type discovered from file command: text/html. See documentation to allow this combination.')
|
57
|
+
spoofed?
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
61
|
it "does not reject if content_type is empty but otherwise checks out" do
|
@@ -29,7 +29,9 @@ describe Paperclip do
|
|
29
29
|
Paperclip.options[:command_path] = "/opt/my_app/bin"
|
30
30
|
Paperclip.run("convert", "stuff")
|
31
31
|
Paperclip.run("convert", "more_stuff")
|
32
|
-
|
32
|
+
|
33
|
+
cmd_path = Paperclip.options[:command_path]
|
34
|
+
assert_equal 1, Cocaine::CommandLine.path.scan(cmd_path).count
|
33
35
|
end
|
34
36
|
end
|
35
37
|
|
@@ -123,33 +125,6 @@ describe Paperclip do
|
|
123
125
|
end
|
124
126
|
end
|
125
127
|
|
126
|
-
if using_protected_attributes?
|
127
|
-
context "that is attr_protected" do
|
128
|
-
before do
|
129
|
-
Dummy.class_eval do
|
130
|
-
attr_protected :avatar
|
131
|
-
end
|
132
|
-
@dummy = Dummy.new
|
133
|
-
end
|
134
|
-
|
135
|
-
it "does not assign the avatar on mass-set" do
|
136
|
-
@dummy.attributes = { other: "I'm set!",
|
137
|
-
avatar: @file }
|
138
|
-
|
139
|
-
assert_equal "I'm set!", @dummy.other
|
140
|
-
assert ! @dummy.avatar?
|
141
|
-
end
|
142
|
-
|
143
|
-
it "allows assigment on normal set" do
|
144
|
-
@dummy.other = "I'm set!"
|
145
|
-
@dummy.avatar = @file
|
146
|
-
|
147
|
-
assert_equal "I'm set!", @dummy.other
|
148
|
-
assert @dummy.avatar?
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
128
|
context "with a subclass" do
|
154
129
|
before do
|
155
130
|
class ::SubDummy < Dummy; end
|