kt-paperclip 7.0.0 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|