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.
Files changed (200) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/custom.md +10 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.github/workflows/reviewdog.yml +23 -0
  7. data/.github/workflows/test.yml +46 -0
  8. data/.gitignore +19 -0
  9. data/.qlty/.gitignore +7 -0
  10. data/.qlty/qlty.toml +89 -0
  11. data/.rubocop.yml +1060 -0
  12. data/Appraisals +29 -0
  13. data/CONTRIBUTING.md +85 -0
  14. data/Gemfile +17 -0
  15. data/LICENSE +25 -0
  16. data/NEWS +567 -0
  17. data/README.md +1083 -0
  18. data/RELEASING.md +17 -0
  19. data/Rakefile +52 -0
  20. data/bin/console +11 -0
  21. data/features/basic_integration.feature +85 -0
  22. data/features/migration.feature +29 -0
  23. data/features/rake_tasks.feature +62 -0
  24. data/features/step_definitions/attachment_steps.rb +121 -0
  25. data/features/step_definitions/html_steps.rb +15 -0
  26. data/features/step_definitions/rails_steps.rb +271 -0
  27. data/features/step_definitions/s3_steps.rb +16 -0
  28. data/features/step_definitions/web_steps.rb +106 -0
  29. data/features/support/env.rb +12 -0
  30. data/features/support/file_helpers.rb +34 -0
  31. data/features/support/fixtures/boot_config.txt +15 -0
  32. data/features/support/fixtures/gemfile.txt +5 -0
  33. data/features/support/fixtures/preinitializer.txt +20 -0
  34. data/features/support/paths.rb +28 -0
  35. data/features/support/rails.rb +39 -0
  36. data/features/support/selectors.rb +19 -0
  37. data/features/support/webmock_setup.rb +8 -0
  38. data/gemfiles/7.0.gemfile +20 -0
  39. data/gemfiles/7.1.gemfile +20 -0
  40. data/gemfiles/7.2.gemfile +20 -0
  41. data/gemfiles/8.0.gemfile +20 -0
  42. data/gemfiles/8.1.gemfile +20 -0
  43. data/lib/generators/paperclip/USAGE +8 -0
  44. data/lib/generators/paperclip/paperclip_generator.rb +36 -0
  45. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
  46. data/lib/jr-paperclip.rb +1 -0
  47. data/lib/paperclip/attachment.rb +634 -0
  48. data/lib/paperclip/attachment_registry.rb +60 -0
  49. data/lib/paperclip/callbacks.rb +42 -0
  50. data/lib/paperclip/content_type_detector.rb +85 -0
  51. data/lib/paperclip/errors.rb +34 -0
  52. data/lib/paperclip/file_command_content_type_detector.rb +28 -0
  53. data/lib/paperclip/filename_cleaner.rb +15 -0
  54. data/lib/paperclip/geometry.rb +157 -0
  55. data/lib/paperclip/geometry_detector_factory.rb +45 -0
  56. data/lib/paperclip/geometry_parser_factory.rb +31 -0
  57. data/lib/paperclip/glue.rb +18 -0
  58. data/lib/paperclip/has_attached_file.rb +116 -0
  59. data/lib/paperclip/helpers.rb +60 -0
  60. data/lib/paperclip/interpolations/plural_cache.rb +18 -0
  61. data/lib/paperclip/interpolations.rb +205 -0
  62. data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
  63. data/lib/paperclip/io_adapters/attachment_adapter.rb +56 -0
  64. data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
  65. data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
  66. data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
  67. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
  68. data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
  69. data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
  70. data/lib/paperclip/io_adapters/registry.rb +36 -0
  71. data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
  72. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
  73. data/lib/paperclip/io_adapters/uri_adapter.rb +78 -0
  74. data/lib/paperclip/locales/en.yml +18 -0
  75. data/lib/paperclip/locales/fr.yml +18 -0
  76. data/lib/paperclip/locales/gd.yml +20 -0
  77. data/lib/paperclip/logger.rb +21 -0
  78. data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
  79. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
  80. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
  81. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
  82. data/lib/paperclip/matchers.rb +64 -0
  83. data/lib/paperclip/media_type_spoof_detector.rb +93 -0
  84. data/lib/paperclip/missing_attachment_styles.rb +84 -0
  85. data/lib/paperclip/processor.rb +56 -0
  86. data/lib/paperclip/processor_helpers.rb +52 -0
  87. data/lib/paperclip/rails_environment.rb +21 -0
  88. data/lib/paperclip/railtie.rb +31 -0
  89. data/lib/paperclip/schema.rb +104 -0
  90. data/lib/paperclip/storage/filesystem.rb +99 -0
  91. data/lib/paperclip/storage/fog.rb +262 -0
  92. data/lib/paperclip/storage/s3.rb +497 -0
  93. data/lib/paperclip/storage.rb +3 -0
  94. data/lib/paperclip/style.rb +106 -0
  95. data/lib/paperclip/tempfile.rb +42 -0
  96. data/lib/paperclip/tempfile_factory.rb +22 -0
  97. data/lib/paperclip/thumbnail.rb +131 -0
  98. data/lib/paperclip/url_generator.rb +83 -0
  99. data/lib/paperclip/validators/attachment_content_type_validator.rb +95 -0
  100. data/lib/paperclip/validators/attachment_file_name_validator.rb +82 -0
  101. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
  102. data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
  103. data/lib/paperclip/validators/attachment_size_validator.rb +126 -0
  104. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
  105. data/lib/paperclip/validators.rb +73 -0
  106. data/lib/paperclip/version.rb +3 -0
  107. data/lib/paperclip.rb +215 -0
  108. data/lib/tasks/paperclip.rake +140 -0
  109. data/paperclip.gemspec +51 -0
  110. data/shoulda_macros/paperclip.rb +134 -0
  111. data/spec/database.yml +4 -0
  112. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  113. data/spec/paperclip/attachment_processing_spec.rb +79 -0
  114. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  115. data/spec/paperclip/attachment_spec.rb +1617 -0
  116. data/spec/paperclip/content_type_detector_spec.rb +58 -0
  117. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  118. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  119. data/spec/paperclip/geometry_detector_spec.rb +47 -0
  120. data/spec/paperclip/geometry_parser_spec.rb +73 -0
  121. data/spec/paperclip/geometry_spec.rb +267 -0
  122. data/spec/paperclip/glue_spec.rb +63 -0
  123. data/spec/paperclip/has_attached_file_spec.rb +78 -0
  124. data/spec/paperclip/integration_spec.rb +702 -0
  125. data/spec/paperclip/interpolations_spec.rb +270 -0
  126. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  127. data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +167 -0
  128. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
  129. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  130. data/spec/paperclip/io_adapters/file_adapter_spec.rb +134 -0
  131. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +142 -0
  132. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  133. data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
  134. data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
  135. data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
  136. data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
  137. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +231 -0
  138. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  139. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
  140. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  141. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  142. data/spec/paperclip/media_type_spoof_detector_spec.rb +126 -0
  143. data/spec/paperclip/meta_class_spec.rb +30 -0
  144. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
  145. data/spec/paperclip/paperclip_spec.rb +196 -0
  146. data/spec/paperclip/plural_cache_spec.rb +37 -0
  147. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  148. data/spec/paperclip/processor_spec.rb +26 -0
  149. data/spec/paperclip/rails_environment_spec.rb +30 -0
  150. data/spec/paperclip/rake_spec.rb +103 -0
  151. data/spec/paperclip/schema_spec.rb +298 -0
  152. data/spec/paperclip/storage/filesystem_spec.rb +102 -0
  153. data/spec/paperclip/storage/fog_spec.rb +606 -0
  154. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  155. data/spec/paperclip/storage/s3_spec.rb +1974 -0
  156. data/spec/paperclip/style_spec.rb +251 -0
  157. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  158. data/spec/paperclip/tempfile_spec.rb +35 -0
  159. data/spec/paperclip/thumbnail_spec.rb +504 -0
  160. data/spec/paperclip/url_generator_spec.rb +231 -0
  161. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +410 -0
  162. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +249 -0
  163. data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
  164. data/spec/paperclip/validators/attachment_size_validator_spec.rb +325 -0
  165. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
  166. data/spec/paperclip/validators_spec.rb +179 -0
  167. data/spec/spec_helper.rb +52 -0
  168. data/spec/support/assertions.rb +84 -0
  169. data/spec/support/fake_model.rb +24 -0
  170. data/spec/support/fake_rails.rb +12 -0
  171. data/spec/support/fixtures/12k.png +0 -0
  172. data/spec/support/fixtures/50x50.png +0 -0
  173. data/spec/support/fixtures/5k.png +0 -0
  174. data/spec/support/fixtures/animated +0 -0
  175. data/spec/support/fixtures/animated.gif +0 -0
  176. data/spec/support/fixtures/animated.unknown +0 -0
  177. data/spec/support/fixtures/aws_s3.yml +13 -0
  178. data/spec/support/fixtures/bad.png +1 -0
  179. data/spec/support/fixtures/empty.html +1 -0
  180. data/spec/support/fixtures/empty.xlsx +0 -0
  181. data/spec/support/fixtures/fog.yml +8 -0
  182. data/spec/support/fixtures/rotated.jpg +0 -0
  183. data/spec/support/fixtures/s3.yml +8 -0
  184. data/spec/support/fixtures/sample.xlsm +0 -0
  185. data/spec/support/fixtures/spaced file.jpg +0 -0
  186. data/spec/support/fixtures/spaced file.png +0 -0
  187. data/spec/support/fixtures/text.txt +1 -0
  188. data/spec/support/fixtures/twopage.pdf +0 -0
  189. data/spec/support/fixtures/uppercase.PNG +0 -0
  190. data/spec/support/matchers/accept.rb +5 -0
  191. data/spec/support/matchers/exist.rb +5 -0
  192. data/spec/support/matchers/have_column.rb +23 -0
  193. data/spec/support/mock_attachment.rb +24 -0
  194. data/spec/support/mock_interpolator.rb +24 -0
  195. data/spec/support/mock_url_generator_builder.rb +26 -0
  196. data/spec/support/model_reconstruction.rb +72 -0
  197. data/spec/support/reporting.rb +11 -0
  198. data/spec/support/test_data.rb +13 -0
  199. data/spec/support/version_helper.rb +9 -0
  200. 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
@@ -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
@@ -0,0 +1,12 @@
1
+ class FakeRails
2
+ def initialize(env, root)
3
+ @env = env
4
+ @root = root
5
+ end
6
+
7
+ attr_accessor :env, :root
8
+
9
+ def const_defined?(_const)
10
+ false
11
+ end
12
+ end
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
@@ -0,0 +1,8 @@
1
+ development:
2
+ provider: AWS
3
+ aws_access_key_id: AWS_ID
4
+ aws_secret_access_key: AWS_SECRET
5
+ test:
6
+ provider: AWS
7
+ aws_access_key_id: AWS_ID
8
+ aws_secret_access_key: AWS_SECRET
Binary file
@@ -0,0 +1,8 @@
1
+ development:
2
+ key: 54321
3
+ production:
4
+ key: 12345
5
+ test:
6
+ bucket: <%= ENV['S3_BUCKET'] %>
7
+ access_key_id: <%= ENV['S3_KEY'] %>
8
+ secret_access_key: <%= ENV['S3_SECRET'] %>
Binary file
@@ -0,0 +1 @@
1
+ paperclip!
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :accept do |expected|
2
+ match do |actual|
3
+ actual.matches?(expected)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :exist do |_expected|
2
+ match do |actual|
3
+ File.exist?(actual)
4
+ end
5
+ end
@@ -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,11 @@
1
+ module Reporting
2
+ def silence_stream(stream)
3
+ old_stream = stream.dup
4
+ stream.reopen(RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ ? "NUL:" : "/dev/null")
5
+ stream.sync = true
6
+ yield
7
+ ensure
8
+ stream.reopen(old_stream)
9
+ old_stream.close
10
+ end
11
+ 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
@@ -0,0 +1,9 @@
1
+ module VersionHelper
2
+ def active_support_version
3
+ ActiveSupport::VERSION::STRING
4
+ end
5
+
6
+ def ruby_version
7
+ RUBY_VERSION
8
+ end
9
+ end