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
data/RELEASING.md ADDED
@@ -0,0 +1,17 @@
1
+ Releasing paperclip
2
+
3
+ 1. Update `lib/paperclip/version.rb` file accordingly.
4
+ 2. Update `NEWS` to reflect the changes since last release.
5
+ 3. Commit changes. There shouldn’t be code changes, and thus CI doesn’t need to
6
+ run, you can then add “[ci skip]” to the commit message.
7
+ 4. Tag the release: `git tag -m 'vVERSION' vVERSION`
8
+ 5. Push changes: `git push --tags`
9
+ 6. Build and publish the gem:
10
+
11
+ ```bash
12
+ gem build paperclip.gemspec
13
+ gem push paperclip-VERSION.gem
14
+ ```
15
+
16
+ 7. Announce the new release, making sure to say “thank you” to the contributors
17
+ who helped shape this version.
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ require "bundler/gem_tasks"
2
+ require "appraisal"
3
+ require "rspec/core/rake_task"
4
+ require "cucumber/rake/task"
5
+
6
+ desc "Default: run unit tests."
7
+ task default: [:clean, :all]
8
+
9
+ desc "Test the paperclip plugin under all supported Rails versions."
10
+ task :all do |_t|
11
+ if ENV["BUNDLE_GEMFILE"]
12
+ exec("rake spec && cucumber")
13
+ else
14
+ exec("rm -f gemfiles/*.lock")
15
+ Rake::Task["appraisal:gemfiles"].execute
16
+ Rake::Task["appraisal:install"].execute
17
+ exec("rake appraisal")
18
+ end
19
+ end
20
+
21
+ desc "Test the paperclip plugin."
22
+ RSpec::Core::RakeTask.new(:spec)
23
+
24
+ desc "Run integration test"
25
+ Cucumber::Rake::Task.new do |t|
26
+ t.cucumber_opts = %w{--format progress}
27
+ end
28
+
29
+ desc "Start an IRB session with all necessary files required."
30
+ task :shell do |_t|
31
+ chdir File.dirname(__FILE__)
32
+ exec "bin/console"
33
+ end
34
+
35
+ desc "Clean up files."
36
+ task :clean do |_t|
37
+ FileUtils.rm_rf "doc"
38
+ FileUtils.rm_rf "tmp"
39
+ FileUtils.rm_rf "pkg"
40
+ FileUtils.rm_rf "public"
41
+ begin
42
+ FileUtils.rm "test/debug.log"
43
+ rescue StandardError
44
+ nil
45
+ end
46
+ begin
47
+ FileUtils.rm "test/paperclip.db"
48
+ rescue StandardError
49
+ nil
50
+ end
51
+ Dir.glob("paperclip-*.gem").each { |f| FileUtils.rm f }
52
+ end
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "logger"
6
+ require "active_record"
7
+ require "tempfile"
8
+ require_relative "../lib/paperclip"
9
+
10
+ require "irb"
11
+ IRB.start
@@ -0,0 +1,85 @@
1
+ Feature: Rails integration
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I run a rails generator to generate a "User" scaffold with "name:string"
6
+ And I run a paperclip generator to add a paperclip "attachment" to the "User" model
7
+ And I run a migration
8
+ And I update my new user view to include the file upload field
9
+ And I update my user view to include the attachment
10
+ And I allow the attachment to be submitted
11
+ And I replace this snippet to app/views/layouts/application.html.erb:
12
+ """
13
+ <%= javascript_tag 'application', 'data-turbolinks-track': 'reload' %>
14
+ """
15
+
16
+ Scenario: Configure defaults for all attachments through Railtie
17
+ Given I add this snippet to config/application.rb:
18
+ """
19
+ config.paperclip_defaults = {
20
+ :url => "/paperclip/custom/:attachment/:style/:filename",
21
+ :validate_media_type => false
22
+ }
23
+ """
24
+ And I attach :attachment
25
+ And I start the rails application
26
+ When I go to the new user page
27
+ And I fill in "Name" with "something"
28
+ And I attach the file "spec/support/fixtures/animated.unknown" to "Attachment"
29
+ And I press "Submit"
30
+ Then I should see "Name: something"
31
+ And I should see an image with a path of "/paperclip/custom/attachments/original/animated.unknown"
32
+ And the file at "/paperclip/custom/attachments/original/animated.unknown" should be the same as "spec/support/fixtures/animated.unknown"
33
+
34
+ Scenario: Add custom processors
35
+ Given I add a "test" processor in "lib/paperclip"
36
+ And I add a "cool" processor in "lib/paperclip"
37
+ And I attach :attachment with:
38
+ """
39
+ styles: { original: {} }, processors: [:test, :cool]
40
+ """
41
+ And I start the rails application
42
+ When I go to the new user page
43
+ And I fill in "Name" with "something"
44
+ And I attach the file "spec/support/fixtures/5k.png" to "Attachment"
45
+ And I press "Submit"
46
+ Then I should see "Name: something"
47
+ And I should see an image with a path of "/paperclip/custom/attachments/original/5k.png"
48
+
49
+ Scenario: Filesystem integration test
50
+ Given I attach :attachment with:
51
+ """
52
+ :url => "/system/:attachment/:style/:filename"
53
+ """
54
+ And I start the rails application
55
+ When I go to the new user page
56
+ And I fill in "Name" with "something"
57
+ And I attach the file "spec/support/fixtures/5k.png" to "Attachment"
58
+ And I press "Submit"
59
+ Then I should see "Name: something"
60
+ And I should see an image with a path of "/system/attachments/original/5k.png"
61
+ And the file at "/system/attachments/original/5k.png" should be the same as "spec/support/fixtures/5k.png"
62
+
63
+ Scenario: S3 Integration test
64
+ Given I attach :attachment with:
65
+ """
66
+ :storage => :s3,
67
+ :path => "/:attachment/:style/:filename",
68
+ :s3_credentials => Rails.root.join("config/s3.yml"),
69
+ :styles => { :square => "100x100#" }
70
+ """
71
+ And I write to "config/s3.yml" with:
72
+ """
73
+ bucket: paperclip
74
+ access_key_id: access_key
75
+ secret_access_key: secret_key
76
+ s3_region: us-west-2
77
+ """
78
+ And I start the rails application
79
+ When I go to the new user page
80
+ And I fill in "Name" with "something"
81
+ And I attach the file "spec/support/fixtures/5k.png" to "Attachment" on S3
82
+ And I press "Submit"
83
+ Then I should see "Name: something"
84
+ And I should see an image with a path of "//s3.amazonaws.com/paperclip/attachments/original/5k.png"
85
+ And the file at "//s3.amazonaws.com/paperclip/attachments/original/5k.png" should be uploaded to S3
@@ -0,0 +1,29 @@
1
+ Feature: Migration
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I generate a "User" model:
6
+
7
+ Scenario: Vintage syntax
8
+ Given I run a paperclip migration to add a paperclip "attach" to the "User" model
9
+
10
+ And I run a migration
11
+ Then I should have attachment columns for "attach"
12
+
13
+ When I rollback a migration
14
+ Then I should not have attachment columns for "attach"
15
+
16
+ Scenario: New syntax with create_table
17
+ Given I run a paperclip migration to add a paperclip "attach" to the "User" model
18
+
19
+ And I run a migration
20
+ Then I should have attachment columns for "attach"
21
+
22
+ Scenario: New syntax outside of create_table
23
+ Given I run a paperclip migration to add a paperclip "attachment_sample" to the "User" model
24
+
25
+ And I run a migration
26
+ Then I should have attachment columns for "attachment_sample"
27
+
28
+ When I rollback a migration
29
+ Then I should not have attachment columns for "attachment_sample"
@@ -0,0 +1,62 @@
1
+ Feature: Rake tasks
2
+
3
+ Background:
4
+ Given I generate a new rails application
5
+ And I run a rails generator to generate a "User" scaffold with "name:string"
6
+ And I run a paperclip generator to add a paperclip "attachment" to the "User" model
7
+ And I run a migration
8
+ And I attach :attachment with:
9
+ """
10
+ :path => ":rails_root/public/system/:attachment/:style/:filename"
11
+ """
12
+
13
+ Scenario: Paperclip refresh thumbnails task
14
+ When I modify my attachment definition to:
15
+ """
16
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
17
+ :styles => { :medium => "200x200#" }
18
+ """
19
+ And I upload the fixture "5k.png"
20
+ Then the attachment "medium/5k.png" should have a dimension of 200x200
21
+ When I modify my attachment definition to:
22
+ """
23
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
24
+ :styles => { :medium => "100x100#" }
25
+ """
26
+ When I successfully run `bundle exec rake paperclip:refresh:thumbnails CLASS=User --trace`
27
+ Then the attachment "original/5k.png" should exist
28
+ And the attachment "medium/5k.png" should have a dimension of 100x100
29
+
30
+ Scenario: Paperclip refresh metadata task
31
+ When I upload the fixture "5k.png"
32
+ And I swap the attachment "original/5k.png" with the fixture "12k.png"
33
+ And I successfully run `bundle exec rake paperclip:refresh:metadata CLASS=User --trace`
34
+ Then the attachment should have the same content type as the fixture "12k.png"
35
+ And the attachment should have the same file size as the fixture "12k.png"
36
+
37
+ Scenario: Paperclip refresh missing styles task
38
+ When I upload the fixture "5k.png"
39
+ Then the attachment file "original/5k.png" should exist
40
+ And the attachment file "medium/5k.png" should not exist
41
+ When I modify my attachment definition to:
42
+ """
43
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename",
44
+ :styles => { :medium => "200x200#" }
45
+ """
46
+ When I successfully run `bundle exec rake paperclip:refresh:missing_styles --trace`
47
+ Then the attachment file "original/5k.png" should exist
48
+ And the attachment file "medium/5k.png" should exist
49
+
50
+ Scenario: Paperclip clean task
51
+ When I upload the fixture "5k.png"
52
+ And I upload the fixture "12k.png"
53
+ Then the attachment file "original/5k.png" should exist
54
+ And the attachment file "original/12k.png" should exist
55
+ When I modify my attachment definition to:
56
+ """
57
+ has_attached_file :attachment, :path => ":rails_root/public/system/:attachment/:style/:filename"
58
+ validates_attachment_size :attachment, :less_than => 10.kilobytes
59
+ """
60
+ And I successfully run `bundle exec rake paperclip:clean CLASS=User --trace`
61
+ Then the attachment file "original/5k.png" should exist
62
+ But the attachment file "original/12k.png" should not exist
@@ -0,0 +1,121 @@
1
+ module AttachmentHelpers
2
+ def fixture_path(filename)
3
+ File.expand_path("#{PROJECT_ROOT}/spec/support/fixtures/#{filename}")
4
+ end
5
+
6
+ def attachment_path(filename)
7
+ File.expand_path("public/system/attachments/#{filename}")
8
+ end
9
+ end
10
+ World(AttachmentHelpers)
11
+
12
+ When /^I modify my attachment definition to:$/ do |definition|
13
+ content = cd(".") { File.read("app/models/user.rb") }
14
+ name = content[/has_attached_file :\w+/][/:\w+/]
15
+ content.gsub!(/has_attached_file.+end/m, <<-FILE)
16
+ #{definition}
17
+ do_not_validate_attachment_file_type #{name}
18
+ end
19
+ FILE
20
+
21
+ write_file "app/models/user.rb", content
22
+ cd(".") { FileUtils.rm_rf ".rbx" }
23
+ end
24
+
25
+ When /^I upload the fixture "([^"]*)"$/ do |filename|
26
+ aruba_run_simple %(bundle exec rails runner "User.create!(:attachment => File.open('#{fixture_path(filename)}'))")
27
+ end
28
+
29
+ Then /^the attachment "([^"]*)" should have a dimension of (\d+x\d+)$/ do |filename, dimension|
30
+ cd(".") do
31
+ geometry = `identify -format "%wx%h" "#{attachment_path(filename)}"`.strip
32
+ expect(geometry).to eq(dimension)
33
+ end
34
+ end
35
+
36
+ Then /^the attachment "([^"]*)" should exist$/ do |filename|
37
+ cd(".") do
38
+ expect(File.exist?(attachment_path(filename))).to be true
39
+ end
40
+ end
41
+
42
+ When /^I swap the attachment "([^"]*)" with the fixture "([^"]*)"$/ do |attachment_filename, fixture_filename|
43
+ cd(".") do
44
+ require "fileutils"
45
+ FileUtils.rm_f attachment_path(attachment_filename)
46
+ FileUtils.cp fixture_path(fixture_filename), attachment_path(attachment_filename)
47
+ end
48
+ end
49
+
50
+ Then /^the attachment should have the same content type as the fixture "([^"]*)"$/ do |filename|
51
+ cd(".") do
52
+ begin
53
+ # Use mime/types/columnar if available, for reduced memory usage
54
+ require "mime/types/columnar"
55
+ rescue LoadError
56
+ require "mime/types"
57
+ end
58
+
59
+ attachment_content_type = `bundle exec rails runner "puts User.last.attachment_content_type"`.strip
60
+ expected = MIME::Types.type_for(filename).first.content_type
61
+ expect(attachment_content_type).to eq(expected)
62
+ end
63
+ end
64
+
65
+ Then /^the attachment should have the same file name as the fixture "([^"]*)"$/ do |filename|
66
+ cd(".") do
67
+ attachment_file_name = `bundle exec rails runner "puts User.last.attachment_file_name"`.strip
68
+ expect(attachment_file_name).to eq(File.name(fixture_path(filename)).to_s)
69
+ end
70
+ end
71
+
72
+ Then /^the attachment should have the same file size as the fixture "([^"]*)"$/ do |filename|
73
+ cd(".") do
74
+ attachment_file_size = `bundle exec rails runner "puts User.last.attachment_file_size"`.strip
75
+ expect(attachment_file_size).to eq(File.size(fixture_path(filename)).to_s)
76
+ end
77
+ end
78
+
79
+ Then /^the attachment file "([^"]*)" should (not )?exist$/ do |filename, not_exist|
80
+ cd(".") do
81
+ if not_exist
82
+ expect(File.exist?(attachment_path(filename))).to be false
83
+ else
84
+ expect(File.exist?(attachment_path(filename))).to be true
85
+ end
86
+ end
87
+ end
88
+
89
+ Then /^I should have attachment columns for "([^"]*)"$/ do |attachment_name|
90
+ cd(".") do
91
+ columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
92
+ expect(columns).to include(["#{attachment_name}_file_name", "varchar"])
93
+ expect(columns).to include(["#{attachment_name}_content_type", "varchar"])
94
+ expect(columns).to include(["#{attachment_name}_file_size", "bigint"])
95
+ # Rails 7+ uses datetime(6) with precision, so match with regex
96
+ datetime_column = columns.find { |col| col[0] == "#{attachment_name}_updated_at" }
97
+ expect(datetime_column).to be_present
98
+ expect(datetime_column[1]).to match(/^datetime/)
99
+ end
100
+ end
101
+
102
+ Then /^I should not have attachment columns for "([^"]*)"$/ do |attachment_name|
103
+ cd(".") do
104
+ columns = eval(`bundle exec rails runner "puts User.columns.map{ |column| [column.name, column.sql_type] }.inspect"`.strip)
105
+ column_names = columns.map { |col| col[0] }
106
+ expect(column_names).not_to include("#{attachment_name}_file_name")
107
+ expect(column_names).not_to include("#{attachment_name}_content_type")
108
+ expect(column_names).not_to include("#{attachment_name}_file_size")
109
+ expect(column_names).not_to include("#{attachment_name}_updated_at")
110
+ end
111
+ end
112
+
113
+ # we have to support different versions of aruba, and this method was renamed for 1.0
114
+ # https://github.com/cucumber/aruba/pull/438
115
+ def aruba_run_simple(*args)
116
+ if respond_to?(:run_simple)
117
+ run_simple(*args)
118
+ elsif respond_to?(:run_command_and_stop)
119
+ run_command_and_stop(*args)
120
+ end
121
+ end
@@ -0,0 +1,15 @@
1
+ Then %r{I should see an image with a path of "([^"]*)"} do |path|
2
+ expect(page).to have_css("img[src^='#{path}']")
3
+ end
4
+
5
+ Then %r{^the file at "([^"]*)" is the same as "([^"]*)"$} do |web_file, path|
6
+ expected = IO.read(path)
7
+ actual = if web_file.match %r{^https?://}
8
+ Net::HTTP.get(URI.parse(web_file))
9
+ else
10
+ visit(web_file)
11
+ page.body
12
+ end
13
+ actual.force_encoding("UTF-8") if actual.respond_to?(:force_encoding)
14
+ expect(actual).to eq(expected)
15
+ end
@@ -0,0 +1,271 @@
1
+ Given /^I generate a new rails application$/ do
2
+ steps %{
3
+ When I successfully run `rails new #{APP_NAME} --skip-bundle --skip-javascript`
4
+ And I cd to "#{APP_NAME}"
5
+ }
6
+
7
+ FileUtils.chdir("tmp/aruba/testapp/")
8
+
9
+ # Remove assets initializer if it exists (causes issues with Rails 8+)
10
+ FileUtils.rm_f("config/initializers/assets.rb")
11
+
12
+ # Determine sqlite3 version based on Rails version
13
+ sqlite3_version = framework_version.to_f >= 7.2 ? ', "~> 2.0"' : ', "~> 1.4"'
14
+
15
+ steps %{
16
+ And I turn off class caching
17
+ And I write to "Gemfile" with:
18
+ """
19
+ source "https://rubygems.org"
20
+ gem "rails", "#{framework_version}"
21
+ gem "sqlite3"#{sqlite3_version}, :platform => [:ruby, :rbx]
22
+ gem "activerecord-jdbcsqlite3-adapter", :platform => :jruby
23
+ gem "jruby-openssl", :platform => :jruby
24
+ gem "capybara"
25
+ gem "gherkin"
26
+ gem "aws-sdk-s3"
27
+ gem "racc", :platform => :rbx
28
+ gem "rubysl", :platform => :rbx
29
+ """
30
+ And I remove turbolinks
31
+ And I comment out lines that contain "action_mailer" in "config/environments/*.rb"
32
+ And I empty the application.js file
33
+ And I configure the application to use "paperclip" from this project
34
+ }
35
+
36
+ FileUtils.chdir("../../..")
37
+ end
38
+
39
+ Given /^I generate a "([^"]*)" model:$/ do |model_name|
40
+ step %[I successfully run `rails generate model #{model_name}`]
41
+ end
42
+
43
+ Given /^I run a paperclip migration to add a paperclip "([^"]*)" to the "([^"]*)" model$/ do |attachment_name, model_name|
44
+ step %[I successfully run `rails generate paperclip #{model_name} #{attachment_name}`]
45
+ end
46
+
47
+ Given "I allow the attachment to be submitted" do
48
+ cd(".") do
49
+ transform_file("app/controllers/users_controller.rb") do |content|
50
+ # Handle both Rails 7 style (require/permit) and Rails 8 style (expect)
51
+ content
52
+ .gsub("params.require(:user).permit(:name)", "params.require(:user).permit!")
53
+ .gsub(/params\.expect\(user: \[.*?\]\)/, "params.require(:user).permit!")
54
+ end
55
+ end
56
+ end
57
+
58
+ Given "I remove turbolinks" do
59
+ cd(".") do
60
+ # These files may not exist in modern Rails (7+)
61
+ transform_file("app/assets/javascripts/application.js") do |content|
62
+ content.gsub("//= require turbolinks", "")
63
+ end
64
+ transform_file("app/views/layouts/application.html.erb") do |content|
65
+ content.gsub(', "data-turbolinks-track" => true', "")
66
+ .gsub(", 'data-turbolinks-track': 'reload'", "")
67
+ end
68
+ end
69
+ end
70
+
71
+ Given /^I comment out lines that contain "([^"]+)" in "([^"]+)"$/ do |contains, glob|
72
+ cd(".") do
73
+ Dir.glob(glob).each do |file|
74
+ transform_file(file) do |content|
75
+ content.gsub(/^(.*?#{contains}.*?)$/) { |line| "# #{line}" }
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ Given /^I attach :attachment$/ do
82
+ attach_attachment("attachment")
83
+ end
84
+
85
+ Given /^I attach :attachment with:$/ do |definition|
86
+ attach_attachment("attachment", definition)
87
+ end
88
+
89
+ def attach_attachment(name, definition = nil)
90
+ snippet = "has_attached_file :#{name}"
91
+ if definition
92
+ snippet += ", \n"
93
+ snippet += definition
94
+ end
95
+ snippet += "\ndo_not_validate_attachment_file_type :#{name}\n"
96
+ cd(".") do
97
+ transform_file("app/models/user.rb") do |content|
98
+ content.sub(/end\Z/, "#{snippet}\nend")
99
+ end
100
+ end
101
+ end
102
+
103
+ Given "I empty the application.js file" do
104
+ cd(".") do
105
+ # This file may not exist in modern Rails (7+) with --skip-asset-pipeline
106
+ transform_file("app/assets/javascripts/application.js") do |_content|
107
+ ""
108
+ end
109
+ end
110
+ end
111
+
112
+ Given /^I run a rails generator to generate a "([^"]*)" scaffold with "([^"]*)"$/ do |model_name, attributes|
113
+ step %[I successfully run `rails generate scaffold #{model_name} #{attributes}`]
114
+ end
115
+
116
+ Given /^I run a paperclip generator to add a paperclip "([^"]*)" to the "([^"]*)" model$/ do |attachment_name, model_name|
117
+ step %[I successfully run `rails generate paperclip #{model_name} #{attachment_name}`]
118
+ end
119
+
120
+ Given /^I run a migration$/ do
121
+ step %[I successfully run `rake db:migrate --trace`]
122
+ end
123
+
124
+ When /^I rollback a migration$/ do
125
+ step %[I successfully run `rake db:rollback STEPS=1 --trace`]
126
+ end
127
+
128
+ Given /^I update my new user view to include the file upload field$/ do
129
+ steps %{
130
+ Given I overwrite "app/views/users/new.html.erb" with:
131
+ """
132
+ <%= form_for @user, :html => { :multipart => true } do |f| %>
133
+ <%= f.label :name %>
134
+ <%= f.text_field :name %>
135
+ <%= f.label :attachment %>
136
+ <%= f.file_field :attachment %>
137
+ <%= submit_tag "Submit" %>
138
+ <% end %>
139
+ """
140
+ }
141
+ end
142
+
143
+ Given /^I update my user view to include the attachment$/ do
144
+ steps %{
145
+ Given I overwrite "app/views/users/show.html.erb" with:
146
+ """
147
+ <p>Name: <%= @user.name %></p>
148
+ <p>Attachment: <%= image_tag @user.attachment.url %></p>
149
+ """
150
+ }
151
+ end
152
+
153
+ Given /^I add this snippet to the User model:$/ do |snippet|
154
+ file_name = "app/models/user.rb"
155
+ cd(".") do
156
+ content = File.read(file_name)
157
+ File.open(file_name, "w") { |f| f << content.sub(/end\Z/, "#{snippet}\nend") }
158
+ end
159
+ end
160
+
161
+ Given /^I add this snippet to config\/application.rb:$/ do |snippet|
162
+ file_name = "config/application.rb"
163
+ cd(".") do
164
+ content = File.read(file_name)
165
+ File.open(file_name, "w") do |f|
166
+ f << content.sub(/class Application < Rails::Application.*$/,
167
+ "class Application < Rails::Application\n#{snippet}\n")
168
+ end
169
+ end
170
+ end
171
+
172
+ Given /^I replace this snippet to app\/views\/layouts\/application.html.erb:$/ do |snippet|
173
+ file_name = "app/views/layouts/application.html.erb"
174
+ cd(".") do
175
+ content = File.read(file_name)
176
+ File.open(file_name, "w") do |f|
177
+ f << content.sub(/<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>$/,
178
+ "#{snippet}")
179
+ end
180
+ end
181
+ end
182
+
183
+ Given /^I start the rails application$/ do
184
+ cd(".") do
185
+ require "rails"
186
+ require "./config/environment"
187
+ require "capybara"
188
+ Capybara.app = Rails.application
189
+ end
190
+ end
191
+
192
+ Given /^I reload my application$/ do
193
+ Rails::Application.reload!
194
+ end
195
+
196
+ When /^I turn off class caching$/ do
197
+ cd(".") do
198
+ file = "config/environments/test.rb"
199
+ config = IO.read(file)
200
+ # Rails 8+ uses enable_reloading instead of cache_classes
201
+ config.gsub!(%r{^\s*config.cache_classes.*$},
202
+ "config.cache_classes = false")
203
+ config.gsub!(%r{^\s*config.enable_reloading.*$},
204
+ "config.enable_reloading = true")
205
+ File.open(file, "w") { |f| f.write(config) }
206
+ end
207
+ end
208
+
209
+ Then /^the file at "([^"]*)" should be the same as "([^"]*)"$/ do |web_file, path|
210
+ expected = IO.read(path)
211
+ actual = read_from_web(web_file)
212
+ expect(actual).to eq(expected)
213
+ end
214
+
215
+ When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
216
+ append_to_gemfile "gem '#{name}', :path => '#{PROJECT_ROOT}'"
217
+ steps %{And I successfully run `bundle install --local`}
218
+ end
219
+
220
+ When /^I configure the application to use "([^\"]+)"$/ do |gem_name|
221
+ append_to_gemfile "gem '#{gem_name}'"
222
+ end
223
+
224
+ When /^I append gems from Appraisal Gemfile$/ do
225
+ File.read(ENV["BUNDLE_GEMFILE"]).split(/\n/).each do |line|
226
+ append_to_gemfile line.strip if line =~ /^gem "(?!rails|appraisal)/
227
+ end
228
+ end
229
+
230
+ When /^I comment out the gem "([^"]*)" from the Gemfile$/ do |gemname|
231
+ comment_out_gem_in_gemfile gemname
232
+ end
233
+
234
+ Given(/^I add a "(.*?)" processor in "(.*?)"$/) do |processor, directory|
235
+ filename = "#{directory}/#{processor}.rb"
236
+ cd(".") do
237
+ FileUtils.mkdir_p directory
238
+ File.open(filename, "w") do |f|
239
+ f.write(<<-CLASS)
240
+ module Paperclip
241
+ class #{processor.capitalize} < Processor
242
+ def make
243
+ basename = File.basename(file.path, File.extname(file.path))
244
+ dst_format = options[:format] ? ".\#{options[:format]}" : ''
245
+
246
+ dst = Tempfile.new([basename, dst_format])
247
+ dst.binmode
248
+
249
+ convert(':src :dst',
250
+ src: File.expand_path(file.path),
251
+ dst: File.expand_path(dst.path)
252
+ )
253
+
254
+ dst
255
+ end
256
+ end
257
+ end
258
+ CLASS
259
+ end
260
+ end
261
+ end
262
+
263
+ def transform_file(filename)
264
+ if File.exist?(filename)
265
+ content = File.read(filename)
266
+ File.open(filename, "w") do |f|
267
+ content = yield(content)
268
+ f.write(content)
269
+ end
270
+ end
271
+ end