kt-paperclip 7.0.0 → 7.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +3 -1057
- data/.rubocop.yml +1059 -1
- data/CONTRIBUTING.md +4 -5
- data/Gemfile +2 -1
- data/NEWS +3 -0
- data/gemfiles/7.0.gemfile +21 -0
- data/lib/paperclip/attachment.rb +1 -1
- data/lib/paperclip/content_type_detector.rb +8 -3
- data/lib/paperclip/storage/filesystem.rb +1 -1
- data/lib/paperclip/storage/fog.rb +1 -1
- data/lib/paperclip/storage/s3.rb +1 -1
- data/lib/paperclip/validators/attachment_file_name_validator.rb +1 -1
- data/lib/paperclip/validators/attachment_size_validator.rb +3 -2
- data/lib/paperclip/version.rb +1 -1
- data/spec/paperclip/content_type_detector_spec.rb +7 -0
- data/spec/paperclip/storage/filesystem_spec.rb +23 -0
- data/spec/paperclip/storage/fog_spec.rb +46 -0
- data/spec/paperclip/storage/s3_spec.rb +13 -0
- data/spec/paperclip/validators_spec.rb +21 -6
- data/spec/support/fixtures/sample.xlsm +0 -0
- metadata +4 -2
data/CONTRIBUTING.md
CHANGED
@@ -10,8 +10,7 @@ Here's a quick guide for contributing:
|
|
10
10
|
|
11
11
|
1. Fork the repo.
|
12
12
|
|
13
|
-
1. Make sure you have ImageMagick and Ghostscript installed. See [this section]
|
14
|
-
(./README.md#image-processor) of the README.
|
13
|
+
1. Make sure you have ImageMagick and Ghostscript installed. See [this section](./README.md#image-processor) of the README.
|
15
14
|
|
16
15
|
1. Run the tests. We only take pull requests with passing tests, and it's great
|
17
16
|
to know that you have a clean slate: `bundle && bundle exec rake`
|
@@ -78,9 +77,9 @@ Syntax
|
|
78
77
|
|
79
78
|
* Two spaces, no tabs.
|
80
79
|
* No trailing whitespace. Blank lines should not have any space.
|
81
|
-
* Prefer
|
82
|
-
* MyClass.my_method(my_arg)
|
83
|
-
* a = b
|
80
|
+
* Prefer `&&` instead of `and` ; prefer `||` instead of `or`.
|
81
|
+
* Use `MyClass.my_method(my_arg)` instead of `MyClass.my_method( my_arg )` or `MyClass.my_method my_arg`.
|
82
|
+
* `a = b` rather than `a=b` .
|
84
83
|
* Follow the conventions you see used in the source already.
|
85
84
|
|
86
85
|
And in case we didn't emphasize it enough: we love tests!
|
data/Gemfile
CHANGED
@@ -12,7 +12,8 @@ group :development, :test do
|
|
12
12
|
gem "builder"
|
13
13
|
gem "listen", "~> 3.0.8"
|
14
14
|
gem "rspec"
|
15
|
-
|
15
|
+
# Hound only supports certain versions of Rubocop -- 1.22.1 is currently the most recent one supported.
|
16
|
+
gem "rubocop", "1.22.1", require: false
|
16
17
|
gem "rubocop-rails"
|
17
18
|
gem "sprockets", "3.7.2"
|
18
19
|
end
|
data/NEWS
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
[UNRELEASED]
|
2
|
+
Issue file delete only once per unique style when nullifying attachment or destroying an object. Avoids triggering a rate limit error on Google Cloud Storage.
|
3
|
+
|
1
4
|
7.0.0 (2021-05-28)
|
2
5
|
* Replace `mimemagic` gem with `marcel` due to licensing issues. See https://github.com/kreeti/kt-paperclip/pull/54 for details and limitations
|
3
6
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "pry"
|
6
|
+
gem "sqlite3", "~> 1.4", platforms: :ruby
|
7
|
+
gem "aruba", "~> 1.0", ">= 1.0.4"
|
8
|
+
gem "rails", "~> 7.0.0"
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem "activerecord-import"
|
12
|
+
gem "bootsnap", require: false
|
13
|
+
gem "builder"
|
14
|
+
gem "listen", "~> 3.0.8"
|
15
|
+
gem "rspec"
|
16
|
+
gem "rubocop", require: false
|
17
|
+
gem "rubocop-rails"
|
18
|
+
gem "sprockets", "3.7.2"
|
19
|
+
end
|
20
|
+
|
21
|
+
gemspec path: "../"
|
data/lib/paperclip/attachment.rb
CHANGED
@@ -38,7 +38,7 @@ module Paperclip
|
|
38
38
|
end
|
39
39
|
|
40
40
|
attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny,
|
41
|
-
:options, :interpolator, :source_file_options
|
41
|
+
:options, :interpolator, :source_file_options, :queued_for_delete
|
42
42
|
attr_accessor :post_processing
|
43
43
|
|
44
44
|
# Creates an Attachment object. +name+ is the name of the attachment,
|
@@ -67,9 +67,14 @@ module Paperclip
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def type_from_marcel
|
70
|
-
@type_from_marcel
|
71
|
-
|
72
|
-
|
70
|
+
return @type_from_marcel if defined? @type_from_marcel
|
71
|
+
|
72
|
+
@type_from_marcel = Marcel::MimeType.for Pathname.new(@filepath),
|
73
|
+
name: @filepath
|
74
|
+
# Marcel::MineType returns 'application/octet-stream' if it can't find
|
75
|
+
# a valid type.
|
76
|
+
@type_from_marcel = nil if @type_from_marcel == SENSIBLE_DEFAULT
|
77
|
+
@type_from_marcel
|
73
78
|
end
|
74
79
|
|
75
80
|
def type_from_file_command
|
data/lib/paperclip/storage/s3.rb
CHANGED
@@ -27,7 +27,7 @@ module Paperclip
|
|
27
27
|
[:both, :base].include?(options[:add_validation_errors_to])
|
28
28
|
|
29
29
|
record.errors[attribute].each do |error|
|
30
|
-
record.errors.add
|
30
|
+
record.errors.add(base_attribute, error)
|
31
31
|
end
|
32
32
|
|
33
33
|
record.errors.delete(attribute) if options[:add_validation_errors_to] == :base
|
@@ -35,8 +35,9 @@ module Paperclip
|
|
35
35
|
options.slice(*AVAILABLE_CHECKS).each do |option, option_value|
|
36
36
|
option_value = option_value.call(record) if option_value.is_a?(Proc)
|
37
37
|
option_value = extract_option_value(option, option_value)
|
38
|
-
|
39
|
-
|
38
|
+
operator = Rails::VERSION::MAJOR >= 7 ? COMPARE_CHECKS[option] : CHECKS[option]
|
39
|
+
|
40
|
+
unless value.send(operator, option_value)
|
40
41
|
error_message_key = options[:in] ? :in_between : option
|
41
42
|
error_attrs.each do |error_attr_name|
|
42
43
|
record.errors.add(error_attr_name, error_message_key, **filtered_options(value).merge(
|
data/lib/paperclip/version.rb
CHANGED
@@ -7,6 +7,13 @@ describe Paperclip::ContentTypeDetector do
|
|
7
7
|
Paperclip::ContentTypeDetector.new(file.path).detect
|
8
8
|
end
|
9
9
|
|
10
|
+
it 'returns a more specific content type based on the filename if it matches
|
11
|
+
multiple content types' do
|
12
|
+
file = File.new(fixture_file('sample.xlsm'))
|
13
|
+
assert_equal 'application/vnd.ms-excel.sheet.macroenabled.12',
|
14
|
+
Paperclip::ContentTypeDetector.new(file.path).detect
|
15
|
+
end
|
16
|
+
|
10
17
|
it "gives a sensible default when the name is empty" do
|
11
18
|
assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new("").detect
|
12
19
|
end
|
@@ -49,6 +49,29 @@ describe Paperclip::Storage::Filesystem do
|
|
49
49
|
assert_equal @file.read, tempfile.read
|
50
50
|
tempfile.close
|
51
51
|
end
|
52
|
+
|
53
|
+
it "only issues a delete call once for each unique attachment style when nullifying attachment" do
|
54
|
+
@dummy.save
|
55
|
+
@dummy.avatar.clear(:thumbnail)
|
56
|
+
@dummy.avatar = nil
|
57
|
+
assert_equal 3, @dummy.avatar.queued_for_delete.size
|
58
|
+
|
59
|
+
expect(FileUtils).to receive(:rm).twice
|
60
|
+
@dummy.save
|
61
|
+
|
62
|
+
FileUtils.rm_rf("tmp")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "only issues a delete call once for each unique attachment style when destroying model" do
|
66
|
+
@dummy.save
|
67
|
+
@dummy.avatar.clear(:thumbnail)
|
68
|
+
assert_equal 1, @dummy.avatar.queued_for_delete.size
|
69
|
+
|
70
|
+
expect(FileUtils).to receive(:rm).twice
|
71
|
+
@dummy.destroy
|
72
|
+
|
73
|
+
FileUtils.rm_rf("tmp")
|
74
|
+
end
|
52
75
|
end
|
53
76
|
|
54
77
|
context "with file that has space in file name" do
|
@@ -7,6 +7,52 @@ describe Paperclip::Storage::Fog do
|
|
7
7
|
context "" do
|
8
8
|
before { Fog.mock! }
|
9
9
|
|
10
|
+
context "deleting attachment styles" do
|
11
|
+
before do
|
12
|
+
rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
|
13
|
+
storage: :fog,
|
14
|
+
url: "/:attachment/:style/:filename",
|
15
|
+
fog_directory: "paperclip",
|
16
|
+
fog_credentials: fixture_file("fog.yml")
|
17
|
+
@file = File.open(fixture_file("5k.png"))
|
18
|
+
@dummy = Dummy.new
|
19
|
+
@dummy.avatar = @file
|
20
|
+
@dummy.save
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
@file.close
|
25
|
+
FileUtils.rm_rf("tmp")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "only issues a delete call once for each unique attachment style when nullifying attachment" do
|
29
|
+
@dummy.avatar.clear(:thumb)
|
30
|
+
@dummy.avatar = nil
|
31
|
+
assert_equal 4, @dummy.avatar.queued_for_delete.size
|
32
|
+
|
33
|
+
original = double("original")
|
34
|
+
medium = double("medium")
|
35
|
+
thumb = double("thumb")
|
36
|
+
|
37
|
+
allow(Fog::AWS::Storage::File).to receive(:new).and_return(original, medium, thumb)
|
38
|
+
|
39
|
+
expect(original).to receive(:destroy).once
|
40
|
+
expect(medium).to receive(:destroy).once
|
41
|
+
expect(thumb).to receive(:destroy).once
|
42
|
+
@dummy.save
|
43
|
+
end
|
44
|
+
|
45
|
+
it "only issues a delete call once for each unique attachment style when destroying model" do
|
46
|
+
@dummy.avatar.clear(:thumb)
|
47
|
+
assert_equal 1, @dummy.avatar.queued_for_delete.size
|
48
|
+
|
49
|
+
file = double("file")
|
50
|
+
allow(Fog::AWS::Storage::File).to receive(:new).and_return(file)
|
51
|
+
expect(file).to receive(:destroy).exactly(3).times
|
52
|
+
@dummy.destroy
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
10
56
|
context "with credentials provided in a path string" do
|
11
57
|
before do
|
12
58
|
rebuild_model styles: { medium: "300x300>", thumb: "100x100>" },
|
@@ -940,6 +940,19 @@ describe Paperclip::Storage::S3 do
|
|
940
940
|
end
|
941
941
|
end
|
942
942
|
|
943
|
+
context "and remove, calling S3 Object destroy once per unique style" do
|
944
|
+
before do
|
945
|
+
allow_any_instance_of(Aws::S3::Object).to receive(:exists?).and_return(true)
|
946
|
+
expect_any_instance_of(Aws::S3::Object).to receive(:delete).once
|
947
|
+
@dummy.avatar.clear(:original)
|
948
|
+
@dummy.destroy
|
949
|
+
end
|
950
|
+
|
951
|
+
it "succeeds" do
|
952
|
+
assert true
|
953
|
+
end
|
954
|
+
end
|
955
|
+
|
943
956
|
context "that the file were missing" do
|
944
957
|
before do
|
945
958
|
allow_any_instance_of(Aws::S3::Object).to receive(:exists?).
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Paperclip::Validators do
|
4
|
+
# required to support a range of rubies
|
5
|
+
def error_attribute_names(error)
|
6
|
+
error.try(:attribute_names) || error.keys
|
7
|
+
end
|
8
|
+
|
4
9
|
context "using the helper" do
|
5
10
|
before do
|
6
11
|
rebuild_class
|
@@ -22,7 +27,9 @@ describe Paperclip::Validators do
|
|
22
27
|
it "prevents you from attaching a file that violates that validation" do
|
23
28
|
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
24
29
|
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
25
|
-
expect(dummy.errors
|
30
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
31
|
+
%i[avatar_content_type avatar avatar_file_size]
|
32
|
+
)
|
26
33
|
assert_raises(RuntimeError) { dummy.valid? }
|
27
34
|
end
|
28
35
|
end
|
@@ -47,21 +54,27 @@ describe Paperclip::Validators do
|
|
47
54
|
it "prevents you from attaching a file that violates all of these validations" do
|
48
55
|
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
49
56
|
dummy = Dummy.new(avatar: File.new(fixture_file("spaced file.png")))
|
50
|
-
expect(dummy.errors
|
57
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
58
|
+
%i[avatar avatar_file_name]
|
59
|
+
)
|
51
60
|
assert_raises(RuntimeError) { dummy.valid? }
|
52
61
|
end
|
53
62
|
|
54
63
|
it "prevents you from attaching a file that violates only first of these validations" do
|
55
64
|
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
56
65
|
dummy = Dummy.new(avatar: File.new(fixture_file("5k.png")))
|
57
|
-
expect(dummy.errors
|
66
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
67
|
+
%i[avatar avatar_file_name]
|
68
|
+
)
|
58
69
|
assert_raises(RuntimeError) { dummy.valid? }
|
59
70
|
end
|
60
71
|
|
61
72
|
it "prevents you from attaching a file that violates only second of these validations" do
|
62
73
|
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
63
74
|
dummy = Dummy.new(avatar: File.new(fixture_file("spaced file.jpg")))
|
64
|
-
expect(dummy.errors
|
75
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
76
|
+
%i[avatar avatar_file_name]
|
77
|
+
)
|
65
78
|
assert_raises(RuntimeError) { dummy.valid? }
|
66
79
|
end
|
67
80
|
|
@@ -88,7 +101,9 @@ describe Paperclip::Validators do
|
|
88
101
|
end
|
89
102
|
end
|
90
103
|
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
91
|
-
expect(dummy.errors
|
104
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
105
|
+
%i[avatar_content_type avatar avatar_file_size]
|
106
|
+
)
|
92
107
|
end
|
93
108
|
|
94
109
|
it "does not validate attachment if title is not present" do
|
@@ -98,7 +113,7 @@ describe Paperclip::Validators do
|
|
98
113
|
end
|
99
114
|
end
|
100
115
|
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
101
|
-
assert_equal [], dummy.errors
|
116
|
+
assert_equal [], error_attribute_names(dummy.errors)
|
102
117
|
end
|
103
118
|
end
|
104
119
|
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kt-paperclip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Surendra Singhi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -394,6 +394,7 @@ files:
|
|
394
394
|
- gemfiles/5.2.gemfile
|
395
395
|
- gemfiles/6.0.gemfile
|
396
396
|
- gemfiles/6.1.gemfile
|
397
|
+
- gemfiles/7.0.gemfile
|
397
398
|
- lib/generators/paperclip/USAGE
|
398
399
|
- lib/generators/paperclip/paperclip_generator.rb
|
399
400
|
- lib/generators/paperclip/templates/paperclip_migration.rb.erb
|
@@ -533,6 +534,7 @@ files:
|
|
533
534
|
- spec/support/fixtures/fog.yml
|
534
535
|
- spec/support/fixtures/rotated.jpg
|
535
536
|
- spec/support/fixtures/s3.yml
|
537
|
+
- spec/support/fixtures/sample.xlsm
|
536
538
|
- spec/support/fixtures/spaced file.jpg
|
537
539
|
- spec/support/fixtures/spaced file.png
|
538
540
|
- spec/support/fixtures/text.txt
|