jr-paperclip 7.3.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 +7 -0
- data/.github/FUNDING.yml +3 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/custom.md +10 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/reviewdog.yml +23 -0
- data/.github/workflows/test.yml +46 -0
- data/.gitignore +19 -0
- data/.qlty/.gitignore +7 -0
- data/.qlty/qlty.toml +89 -0
- data/.rubocop.yml +1060 -0
- data/Appraisals +29 -0
- data/CONTRIBUTING.md +85 -0
- data/Gemfile +17 -0
- data/LICENSE +25 -0
- data/NEWS +567 -0
- data/README.md +1083 -0
- data/RELEASING.md +17 -0
- data/Rakefile +52 -0
- data/bin/console +11 -0
- data/features/basic_integration.feature +85 -0
- data/features/migration.feature +29 -0
- data/features/rake_tasks.feature +62 -0
- data/features/step_definitions/attachment_steps.rb +121 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +271 -0
- data/features/step_definitions/s3_steps.rb +16 -0
- data/features/step_definitions/web_steps.rb +106 -0
- data/features/support/env.rb +12 -0
- data/features/support/file_helpers.rb +34 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +39 -0
- data/features/support/selectors.rb +19 -0
- data/features/support/webmock_setup.rb +8 -0
- data/gemfiles/7.0.gemfile +20 -0
- data/gemfiles/7.1.gemfile +20 -0
- data/gemfiles/7.2.gemfile +20 -0
- data/gemfiles/8.0.gemfile +20 -0
- data/gemfiles/8.1.gemfile +20 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +36 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
- data/lib/jr-paperclip.rb +1 -0
- data/lib/paperclip/attachment.rb +634 -0
- data/lib/paperclip/attachment_registry.rb +60 -0
- data/lib/paperclip/callbacks.rb +42 -0
- data/lib/paperclip/content_type_detector.rb +85 -0
- data/lib/paperclip/errors.rb +34 -0
- data/lib/paperclip/file_command_content_type_detector.rb +28 -0
- data/lib/paperclip/filename_cleaner.rb +15 -0
- data/lib/paperclip/geometry.rb +157 -0
- data/lib/paperclip/geometry_detector_factory.rb +45 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +18 -0
- data/lib/paperclip/has_attached_file.rb +116 -0
- data/lib/paperclip/helpers.rb +60 -0
- data/lib/paperclip/interpolations/plural_cache.rb +18 -0
- data/lib/paperclip/interpolations.rb +205 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +56 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
- data/lib/paperclip/io_adapters/registry.rb +36 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +78 -0
- data/lib/paperclip/locales/en.yml +18 -0
- data/lib/paperclip/locales/fr.yml +18 -0
- data/lib/paperclip/locales/gd.yml +20 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/media_type_spoof_detector.rb +93 -0
- data/lib/paperclip/missing_attachment_styles.rb +84 -0
- data/lib/paperclip/processor.rb +56 -0
- data/lib/paperclip/processor_helpers.rb +52 -0
- data/lib/paperclip/rails_environment.rb +21 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +104 -0
- data/lib/paperclip/storage/filesystem.rb +99 -0
- data/lib/paperclip/storage/fog.rb +262 -0
- data/lib/paperclip/storage/s3.rb +497 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/style.rb +106 -0
- data/lib/paperclip/tempfile.rb +42 -0
- data/lib/paperclip/tempfile_factory.rb +22 -0
- data/lib/paperclip/thumbnail.rb +131 -0
- data/lib/paperclip/url_generator.rb +83 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +95 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +82 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +126 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
- data/lib/paperclip/validators.rb +73 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/paperclip.rb +215 -0
- data/lib/tasks/paperclip.rake +140 -0
- data/paperclip.gemspec +51 -0
- data/shoulda_macros/paperclip.rb +134 -0
- data/spec/database.yml +4 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/spec/paperclip/attachment_processing_spec.rb +79 -0
- data/spec/paperclip/attachment_registry_spec.rb +158 -0
- data/spec/paperclip/attachment_spec.rb +1617 -0
- data/spec/paperclip/content_type_detector_spec.rb +58 -0
- data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
- data/spec/paperclip/filename_cleaner_spec.rb +13 -0
- data/spec/paperclip/geometry_detector_spec.rb +47 -0
- data/spec/paperclip/geometry_parser_spec.rb +73 -0
- data/spec/paperclip/geometry_spec.rb +267 -0
- data/spec/paperclip/glue_spec.rb +63 -0
- data/spec/paperclip/has_attached_file_spec.rb +78 -0
- data/spec/paperclip/integration_spec.rb +702 -0
- data/spec/paperclip/interpolations_spec.rb +270 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +167 -0
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +134 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +142 -0
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
- data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +231 -0
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +126 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
- data/spec/paperclip/paperclip_spec.rb +196 -0
- data/spec/paperclip/plural_cache_spec.rb +37 -0
- data/spec/paperclip/processor_helpers_spec.rb +57 -0
- data/spec/paperclip/processor_spec.rb +26 -0
- data/spec/paperclip/rails_environment_spec.rb +30 -0
- data/spec/paperclip/rake_spec.rb +103 -0
- data/spec/paperclip/schema_spec.rb +298 -0
- data/spec/paperclip/storage/filesystem_spec.rb +102 -0
- data/spec/paperclip/storage/fog_spec.rb +606 -0
- data/spec/paperclip/storage/s3_live_spec.rb +188 -0
- data/spec/paperclip/storage/s3_spec.rb +1974 -0
- data/spec/paperclip/style_spec.rb +251 -0
- data/spec/paperclip/tempfile_factory_spec.rb +33 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +504 -0
- data/spec/paperclip/url_generator_spec.rb +231 -0
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +410 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +249 -0
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +325 -0
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
- data/spec/paperclip/validators_spec.rb +179 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/support/assertions.rb +84 -0
- data/spec/support/fake_model.rb +24 -0
- data/spec/support/fake_rails.rb +12 -0
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/aws_s3.yml +13 -0
- data/spec/support/fixtures/bad.png +1 -0
- data/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +8 -0
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +8 -0
- data/spec/support/fixtures/sample.xlsm +0 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +1 -0
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/spec/support/matchers/have_column.rb +23 -0
- data/spec/support/mock_attachment.rb +24 -0
- data/spec/support/mock_interpolator.rb +24 -0
- data/spec/support/mock_url_generator_builder.rb +26 -0
- data/spec/support/model_reconstruction.rb +72 -0
- data/spec/support/reporting.rb +11 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +702 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
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
|
+
|
|
9
|
+
context "using the helper" do
|
|
10
|
+
before do
|
|
11
|
+
rebuild_class
|
|
12
|
+
Dummy.validates_attachment :avatar, presence: true, content_type: { content_type: "image/jpeg" }, size: { in: 0..10240 }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "adds the attachment_presence validator to the class" do
|
|
16
|
+
assert Dummy.validators_on(:avatar).any? { |validator| validator.kind == :attachment_presence }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "adds the attachment_content_type validator to the class" do
|
|
20
|
+
assert Dummy.validators_on(:avatar).any? { |validator| validator.kind == :attachment_content_type }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "adds the attachment_size validator to the class" do
|
|
24
|
+
assert Dummy.validators_on(:avatar).any? { |validator| validator.kind == :attachment_size }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "prevents you from attaching a file that violates that validation" do
|
|
28
|
+
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
|
29
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
30
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
|
31
|
+
%i[avatar_content_type avatar avatar_file_size]
|
|
32
|
+
)
|
|
33
|
+
assert_raises(RuntimeError) { dummy.valid? }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "using the helper with array of validations" do
|
|
38
|
+
before do
|
|
39
|
+
rebuild_class
|
|
40
|
+
Dummy.validates_attachment :avatar, file_type_ignorance: true, file_name: [
|
|
41
|
+
{ matches: /\A.*\.jpe?g\z/i, message: :invalid_extension },
|
|
42
|
+
{ matches: /\A.{,8}\..+\z/i, message: [:too_long, count: 8] },
|
|
43
|
+
]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "adds the attachment_file_name validator to the class" do
|
|
47
|
+
assert Dummy.validators_on(:avatar).any? { |validator| validator.kind == :attachment_file_name }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "adds the attachment_file_name validator with two validations" do
|
|
51
|
+
assert_equal 2, Dummy.validators_on(:avatar).select { |validator| validator.kind == :attachment_file_name }.size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "prevents you from attaching a file that violates all of these validations" do
|
|
55
|
+
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
|
56
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("spaced file.png")))
|
|
57
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
|
58
|
+
%i[avatar avatar_file_name]
|
|
59
|
+
)
|
|
60
|
+
assert_raises(RuntimeError) { dummy.valid? }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "prevents you from attaching a file that violates only first of these validations" do
|
|
64
|
+
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
|
65
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("5k.png")))
|
|
66
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
|
67
|
+
%i[avatar avatar_file_name]
|
|
68
|
+
)
|
|
69
|
+
assert_raises(RuntimeError) { dummy.valid? }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "prevents you from attaching a file that violates only second of these validations" do
|
|
73
|
+
Dummy.class_eval { validate(:name) { raise "DO NOT RUN THIS" } }
|
|
74
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("spaced file.jpg")))
|
|
75
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
|
76
|
+
%i[avatar avatar_file_name]
|
|
77
|
+
)
|
|
78
|
+
assert_raises(RuntimeError) { dummy.valid? }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "allows you to attach a file that does not violate these validations" do
|
|
82
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("rotated.jpg")))
|
|
83
|
+
expect(dummy.errors.full_messages).to be_empty
|
|
84
|
+
assert dummy.valid?
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context "using the helper with a conditional" do
|
|
89
|
+
before do
|
|
90
|
+
rebuild_class
|
|
91
|
+
Dummy.validates_attachment :avatar, presence: true,
|
|
92
|
+
content_type: { content_type: "image/jpeg" },
|
|
93
|
+
size: { in: 0..10240 },
|
|
94
|
+
if: :title_present?
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "validates the attachment if title is present" do
|
|
98
|
+
Dummy.class_eval do
|
|
99
|
+
def title_present?
|
|
100
|
+
true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
104
|
+
expect(error_attribute_names(dummy.errors)).to match_array(
|
|
105
|
+
%i[avatar_content_type avatar avatar_file_size]
|
|
106
|
+
)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "does not validate attachment if title is not present" do
|
|
110
|
+
Dummy.class_eval do
|
|
111
|
+
def title_present?
|
|
112
|
+
false
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
dummy = Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
116
|
+
assert_equal [], error_attribute_names(dummy.errors)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "with no other validations on the Dummy#avatar attachment" do
|
|
121
|
+
before do
|
|
122
|
+
reset_class("Dummy")
|
|
123
|
+
Dummy.has_attached_file :avatar
|
|
124
|
+
Paperclip.reset_duplicate_clash_check!
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "raises an error when no content_type validation exists" do
|
|
128
|
+
assert_raises(Paperclip::Errors::MissingRequiredValidatorError) do
|
|
129
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "does not raise an error when a content_type validation exists" do
|
|
134
|
+
Dummy.validates_attachment :avatar, content_type: { content_type: "image/jpeg" }
|
|
135
|
+
|
|
136
|
+
assert_nothing_raised do
|
|
137
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "does not raise an error when a content_type validation exists using validates_with" do
|
|
142
|
+
Dummy.validates_with Paperclip::Validators::AttachmentContentTypeValidator, attributes: :attachment, content_type: "images/jpeg"
|
|
143
|
+
|
|
144
|
+
assert_nothing_raised do
|
|
145
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "does not raise an error when an inherited validator is used" do
|
|
150
|
+
class MyValidator < Paperclip::Validators::AttachmentContentTypeValidator
|
|
151
|
+
def initialize(options)
|
|
152
|
+
options[:content_type] = "images/jpeg" unless options.key?(:content_type)
|
|
153
|
+
super
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
Dummy.validates_with MyValidator, attributes: :attachment
|
|
157
|
+
|
|
158
|
+
assert_nothing_raised do
|
|
159
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "does not raise an error when a file_name validation exists" do
|
|
164
|
+
Dummy.validates_attachment :avatar, file_name: { matches: /png$/ }
|
|
165
|
+
|
|
166
|
+
assert_nothing_raised do
|
|
167
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "does not raise an error when a the validation has been explicitly rejected" do
|
|
172
|
+
Dummy.validates_attachment :avatar, file_type_ignorance: true
|
|
173
|
+
|
|
174
|
+
assert_nothing_raised do
|
|
175
|
+
Dummy.new(avatar: File.new(fixture_file("12k.png")))
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require "rubygems"
|
|
2
|
+
require "rspec"
|
|
3
|
+
require "active_record"
|
|
4
|
+
require "active_record/version"
|
|
5
|
+
require "active_support"
|
|
6
|
+
require "active_support/core_ext"
|
|
7
|
+
require "ostruct"
|
|
8
|
+
require "pathname"
|
|
9
|
+
require "activerecord-import"
|
|
10
|
+
require "yaml"
|
|
11
|
+
|
|
12
|
+
ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), "..")))
|
|
13
|
+
|
|
14
|
+
puts "Testing against version #{ActiveRecord::VERSION::STRING}"
|
|
15
|
+
|
|
16
|
+
$LOAD_PATH << File.join(ROOT, "lib")
|
|
17
|
+
$LOAD_PATH << File.join(ROOT, "lib", "paperclip")
|
|
18
|
+
require File.join(ROOT, "lib", "paperclip.rb")
|
|
19
|
+
|
|
20
|
+
FIXTURES_DIR = File.join(File.dirname(__FILE__), "fixtures")
|
|
21
|
+
config = YAML::safe_load(IO.read(File.dirname(__FILE__) + "/database.yml"))
|
|
22
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
|
23
|
+
ActiveRecord::Base.establish_connection(config["test"])
|
|
24
|
+
ActiveRecord::Migration.verbose = false
|
|
25
|
+
if ActiveRecord::VERSION::STRING >= "4.2" &&
|
|
26
|
+
ActiveRecord::VERSION::STRING < "5.0"
|
|
27
|
+
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
|
28
|
+
end
|
|
29
|
+
Paperclip.options[:logger] = ActiveRecord::Base.logger
|
|
30
|
+
|
|
31
|
+
Dir[File.join(ROOT, "spec", "support", "**", "*.rb")].each { |f| require f }
|
|
32
|
+
|
|
33
|
+
Rails = FakeRails.new("test", Pathname.new(ROOT).join("tmp"))
|
|
34
|
+
|
|
35
|
+
# Silence deprecation warnings - handle different Rails versions
|
|
36
|
+
if ActiveSupport::Deprecation.respond_to?(:silenced=)
|
|
37
|
+
ActiveSupport::Deprecation.silenced = true
|
|
38
|
+
elsif defined?(ActiveSupport.deprecator)
|
|
39
|
+
ActiveSupport.deprecator.behavior = :silence
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
RSpec.configure do |config|
|
|
43
|
+
config.include Assertions
|
|
44
|
+
config.include ModelReconstruction
|
|
45
|
+
config.include TestData
|
|
46
|
+
config.include Reporting
|
|
47
|
+
config.extend VersionHelper
|
|
48
|
+
|
|
49
|
+
config.before(:all) do
|
|
50
|
+
rebuild_model
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Assertions
|
|
2
|
+
def assert(truthy, message = nil)
|
|
3
|
+
expect(!!truthy).to(eq(true), message)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def assert_equal(expected, actual, message = nil)
|
|
7
|
+
expect(actual).to(eq(expected), message)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def assert_not_equal(expected, actual, message = nil)
|
|
11
|
+
expect(actual).to_not(eq(expected), message)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def assert_raises(exception_class, message = nil, &block)
|
|
15
|
+
expect(&block).to raise_error(exception_class, message)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def assert_nothing_raised(&block)
|
|
19
|
+
expect(&block).to_not raise_error
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def assert_nil(thing)
|
|
23
|
+
expect(thing).to be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def assert_contains(haystack, needle)
|
|
27
|
+
expect(haystack).to include(needle)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def assert_match(pattern, value)
|
|
31
|
+
expect(value).to match(pattern)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def assert_no_match(pattern, value)
|
|
35
|
+
expect(value).to_not match(pattern)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def assert_file_exists(path_to_file)
|
|
39
|
+
expect(path_to_file).to exist
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def assert_file_not_exists(path_to_file)
|
|
43
|
+
expect(path_to_file).to_not exist
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def assert_empty(object)
|
|
47
|
+
expect(object).to be_empty
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def assert_success_response(url)
|
|
51
|
+
url = "http:#{url}" unless url =~ /http/
|
|
52
|
+
Net::HTTP.get_response(URI.parse(url)) do |response|
|
|
53
|
+
assert_equal "200",
|
|
54
|
+
response.code,
|
|
55
|
+
"Expected HTTP response code 200, got #{response.code}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def assert_not_found_response(url)
|
|
60
|
+
url = "http:#{url}" unless url =~ /http/
|
|
61
|
+
Net::HTTP.get_response(URI.parse(url)) do |response|
|
|
62
|
+
assert_equal "404", response.code,
|
|
63
|
+
"Expected HTTP response code 404, got #{response.code}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def assert_forbidden_response(url)
|
|
68
|
+
url = "http:#{url}" unless url =~ /http/
|
|
69
|
+
Net::HTTP.get_response(URI.parse(url)) do |response|
|
|
70
|
+
assert_equal "403", response.code,
|
|
71
|
+
"Expected HTTP response code 403, got #{response.code}"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def assert_frame_dimensions(range, frames)
|
|
76
|
+
frames.each_with_index do |frame, frame_index|
|
|
77
|
+
frame.split("x").each_with_index do |dimension, dimension_index|
|
|
78
|
+
assert range.include?(dimension.to_i),
|
|
79
|
+
"Frame #{frame_index}[#{dimension_index}] should have been within #{range.inspect},
|
|
80
|
+
but was #{dimension}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class FakeModel
|
|
2
|
+
attr_accessor(
|
|
3
|
+
:avatar_file_name,
|
|
4
|
+
:avatar_file_size,
|
|
5
|
+
:avatar_updated_at,
|
|
6
|
+
:avatar_content_type,
|
|
7
|
+
:avatar_fingerprint,
|
|
8
|
+
:id
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
def errors
|
|
12
|
+
@errors ||= []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run_paperclip_callbacks(name, *args); end
|
|
16
|
+
|
|
17
|
+
def valid?
|
|
18
|
+
errors.empty?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def new_record?
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
default: &default
|
|
2
|
+
acl: public-read
|
|
3
|
+
development:
|
|
4
|
+
<<: *default
|
|
5
|
+
key: 54321
|
|
6
|
+
production:
|
|
7
|
+
<<: *default
|
|
8
|
+
key: 12345
|
|
9
|
+
test:
|
|
10
|
+
<<: *default
|
|
11
|
+
bucket: <%= ENV['S3_BUCKET'] %>
|
|
12
|
+
access_key_id: <%= ENV['S3_KEY'] %>
|
|
13
|
+
secret_access_key: <%= ENV['S3_SECRET'] %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This is not an image.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<html></html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
paperclip!
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
RSpec::Matchers.define :have_column do |column_name|
|
|
2
|
+
chain :with_default do |default|
|
|
3
|
+
@default = default
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
match do |columns|
|
|
7
|
+
column = columns.detect { |column| column.name == column_name }
|
|
8
|
+
column && column.default.to_s == @default.to_s
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
failure_message_method =
|
|
12
|
+
if RSpec::Version::STRING.to_i >= 3
|
|
13
|
+
:failure_message
|
|
14
|
+
else
|
|
15
|
+
:failure_message_for_should
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
send(failure_message_method) do |columns|
|
|
19
|
+
"expected to find '#{column_name}', " +
|
|
20
|
+
"default '#{@default}' " +
|
|
21
|
+
"in #{columns.map { |column| [column.name, column.default] }}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class MockAttachment
|
|
2
|
+
attr_accessor :updated_at, :original_filename
|
|
3
|
+
attr_reader :options
|
|
4
|
+
|
|
5
|
+
def initialize(options = {})
|
|
6
|
+
@options = options
|
|
7
|
+
@model = options[:model]
|
|
8
|
+
@responds_to_updated_at = options[:responds_to_updated_at]
|
|
9
|
+
@updated_at = options[:updated_at]
|
|
10
|
+
@original_filename = options[:original_filename]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def instance
|
|
14
|
+
@model
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def respond_to?(meth)
|
|
18
|
+
if meth.to_s == "updated_at"
|
|
19
|
+
@responds_to_updated_at || @updated_at
|
|
20
|
+
else
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class MockInterpolator
|
|
2
|
+
def initialize(options = {})
|
|
3
|
+
@options = options
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def interpolate(pattern, attachment, style_name)
|
|
7
|
+
@interpolated_pattern = pattern
|
|
8
|
+
@interpolated_attachment = attachment
|
|
9
|
+
@interpolated_style_name = style_name
|
|
10
|
+
@options[:result]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def has_interpolated_pattern?(pattern)
|
|
14
|
+
@interpolated_pattern == pattern
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def has_interpolated_style_name?(style_name)
|
|
18
|
+
@interpolated_style_name == style_name
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def has_interpolated_attachment?(attachment)
|
|
22
|
+
@interpolated_attachment == attachment
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class MockUrlGeneratorBuilder
|
|
2
|
+
def initializer; end
|
|
3
|
+
|
|
4
|
+
def new(attachment)
|
|
5
|
+
@attachment = attachment
|
|
6
|
+
@attachment_options = @attachment.options
|
|
7
|
+
self
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def for(style_name, options)
|
|
11
|
+
@generated_url_with_style_name = style_name
|
|
12
|
+
@generated_url_with_options = options
|
|
13
|
+
"hello"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def has_generated_url_with_options?(options)
|
|
17
|
+
# options.is_a_subhash_of(@generated_url_with_options)
|
|
18
|
+
options.inject(true) do |acc, (k, v)|
|
|
19
|
+
acc && @generated_url_with_options[k] == v
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def has_generated_url_with_style_name?(style_name)
|
|
24
|
+
@generated_url_with_style_name == style_name
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module ModelReconstruction
|
|
2
|
+
def reset_class(class_name)
|
|
3
|
+
ActiveRecord::Base.include Paperclip::Glue
|
|
4
|
+
begin
|
|
5
|
+
Object.send(:remove_const, class_name)
|
|
6
|
+
rescue StandardError
|
|
7
|
+
nil
|
|
8
|
+
end
|
|
9
|
+
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
|
|
10
|
+
|
|
11
|
+
klass.class_eval do
|
|
12
|
+
include Paperclip::Glue
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
klass.reset_column_information
|
|
16
|
+
klass.connection_pool.clear_table_cache!(klass.table_name) if klass.connection_pool.respond_to?(:clear_table_cache!)
|
|
17
|
+
|
|
18
|
+
if klass.connection.respond_to?(:schema_cache)
|
|
19
|
+
if ActiveRecord::VERSION::STRING >= "5.0"
|
|
20
|
+
klass.connection.schema_cache.clear_data_source_cache!(klass.table_name)
|
|
21
|
+
else
|
|
22
|
+
klass.connection.schema_cache.clear_table_cache!(klass.table_name)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
klass
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def reset_table(_table_name, &block)
|
|
30
|
+
block ||= lambda { |_table| true }
|
|
31
|
+
ActiveRecord::Migration.create_table :dummies, **{ force: true }, &block
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def modify_table(&block)
|
|
35
|
+
ActiveRecord::Migration.change_table :dummies, &block
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def rebuild_model(options = {})
|
|
39
|
+
ActiveRecord::Migration.create_table :dummies, force: true do |table|
|
|
40
|
+
table.column :title, :string
|
|
41
|
+
table.column :other, :string
|
|
42
|
+
table.column :avatar_file_name, :string
|
|
43
|
+
table.column :avatar_content_type, :string
|
|
44
|
+
table.column :avatar_file_size, :bigint
|
|
45
|
+
table.column :avatar_updated_at, :datetime
|
|
46
|
+
table.column :avatar_fingerprint, :string
|
|
47
|
+
end
|
|
48
|
+
rebuild_class options
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def rebuild_class(options = {})
|
|
52
|
+
reset_class("Dummy").tap do |klass|
|
|
53
|
+
klass.has_attached_file :avatar, options
|
|
54
|
+
klass.do_not_validate_attachment_file_type :avatar
|
|
55
|
+
Paperclip.reset_duplicate_clash_check!
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def rebuild_meta_class_of(obj, options = {})
|
|
60
|
+
meta_class_of(obj).tap do |metaklass|
|
|
61
|
+
metaklass.has_attached_file :avatar, options
|
|
62
|
+
metaklass.do_not_validate_attachment_file_type :avatar
|
|
63
|
+
Paperclip.reset_duplicate_clash_check!
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def meta_class_of(obj)
|
|
68
|
+
class << obj
|
|
69
|
+
self
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module TestData
|
|
2
|
+
def attachment(options = {})
|
|
3
|
+
Paperclip::Attachment.new(:avatar, FakeModel.new, options)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def stringy_file
|
|
7
|
+
StringIO.new('.\n')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def fixture_file(filename)
|
|
11
|
+
File.join(File.dirname(__FILE__), "fixtures", filename)
|
|
12
|
+
end
|
|
13
|
+
end
|