paperclip 3.5.4 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +3 -0
  4. data/.gitignore +0 -6
  5. data/.hound.yml +1055 -0
  6. data/.rubocop.yml +1 -0
  7. data/.travis.yml +17 -20
  8. data/Appraisals +4 -16
  9. data/CONTRIBUTING.md +29 -13
  10. data/Gemfile +11 -3
  11. data/LICENSE +1 -3
  12. data/MIGRATING-ES.md +317 -0
  13. data/MIGRATING.md +375 -0
  14. data/NEWS +262 -49
  15. data/README.md +496 -169
  16. data/RELEASING.md +17 -0
  17. data/Rakefile +6 -8
  18. data/UPGRADING +12 -9
  19. data/features/basic_integration.feature +27 -8
  20. data/features/migration.feature +0 -24
  21. data/features/step_definitions/attachment_steps.rb +44 -36
  22. data/features/step_definitions/html_steps.rb +2 -2
  23. data/features/step_definitions/rails_steps.rb +68 -37
  24. data/features/step_definitions/s3_steps.rb +2 -2
  25. data/features/step_definitions/web_steps.rb +1 -103
  26. data/features/support/env.rb +3 -2
  27. data/features/support/file_helpers.rb +2 -2
  28. data/features/support/fixtures/gemfile.txt +1 -1
  29. data/features/support/paths.rb +1 -1
  30. data/features/support/rails.rb +2 -25
  31. data/gemfiles/4.2.gemfile +17 -0
  32. data/gemfiles/5.0.gemfile +17 -0
  33. data/lib/generators/paperclip/paperclip_generator.rb +9 -3
  34. data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +2 -2
  35. data/lib/paperclip/attachment.rb +170 -52
  36. data/lib/paperclip/attachment_registry.rb +3 -2
  37. data/lib/paperclip/callbacks.rb +13 -1
  38. data/lib/paperclip/content_type_detector.rb +26 -22
  39. data/lib/paperclip/errors.rb +8 -1
  40. data/lib/paperclip/file_command_content_type_detector.rb +6 -8
  41. data/lib/paperclip/filename_cleaner.rb +0 -1
  42. data/lib/paperclip/geometry_detector_factory.rb +6 -4
  43. data/lib/paperclip/geometry_parser_factory.rb +1 -1
  44. data/lib/paperclip/glue.rb +1 -1
  45. data/lib/paperclip/has_attached_file.rb +17 -1
  46. data/lib/paperclip/helpers.rb +15 -11
  47. data/lib/paperclip/interpolations/plural_cache.rb +6 -5
  48. data/lib/paperclip/interpolations.rb +31 -13
  49. data/lib/paperclip/io_adapters/abstract_adapter.rb +34 -5
  50. data/lib/paperclip/io_adapters/attachment_adapter.rb +19 -8
  51. data/lib/paperclip/io_adapters/data_uri_adapter.rb +11 -16
  52. data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
  53. data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
  54. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +8 -7
  55. data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
  56. data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
  57. data/lib/paperclip/io_adapters/registry.rb +6 -2
  58. data/lib/paperclip/io_adapters/stringio_adapter.rb +15 -16
  59. data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
  60. data/lib/paperclip/io_adapters/uri_adapter.rb +43 -19
  61. data/lib/paperclip/locales/en.yml +1 -0
  62. data/lib/paperclip/logger.rb +1 -1
  63. data/lib/paperclip/matchers/have_attached_file_matcher.rb +2 -1
  64. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  65. data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +2 -1
  66. data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +2 -1
  67. data/lib/paperclip/media_type_spoof_detector.rb +93 -0
  68. data/lib/paperclip/processor.rb +15 -43
  69. data/lib/paperclip/processor_helpers.rb +50 -0
  70. data/lib/paperclip/rails_environment.rb +25 -0
  71. data/lib/paperclip/schema.rb +10 -8
  72. data/lib/paperclip/storage/filesystem.rb +14 -3
  73. data/lib/paperclip/storage/fog.rb +38 -20
  74. data/lib/paperclip/storage/s3.rb +124 -73
  75. data/lib/paperclip/style.rb +8 -3
  76. data/lib/paperclip/tempfile_factory.rb +5 -1
  77. data/lib/paperclip/thumbnail.rb +34 -19
  78. data/lib/paperclip/url_generator.rb +26 -14
  79. data/lib/paperclip/validators/attachment_content_type_validator.rb +4 -0
  80. data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
  81. data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
  82. data/lib/paperclip/validators/attachment_presence_validator.rb +4 -0
  83. data/lib/paperclip/validators/attachment_size_validator.rb +5 -3
  84. data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +31 -0
  85. data/lib/paperclip/validators.rb +11 -4
  86. data/lib/paperclip/version.rb +3 -1
  87. data/lib/paperclip.rb +31 -11
  88. data/lib/tasks/paperclip.rake +34 -5
  89. data/paperclip.gemspec +21 -16
  90. data/shoulda_macros/paperclip.rb +0 -1
  91. data/spec/paperclip/attachment_definitions_spec.rb +13 -0
  92. data/{test/attachment_processing_test.rb → spec/paperclip/attachment_processing_spec.rb} +17 -21
  93. data/spec/paperclip/attachment_registry_spec.rb +158 -0
  94. data/{test/attachment_test.rb → spec/paperclip/attachment_spec.rb} +519 -409
  95. data/{test/content_type_detector_test.rb → spec/paperclip/content_type_detector_spec.rb} +17 -20
  96. data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
  97. data/spec/paperclip/filename_cleaner_spec.rb +13 -0
  98. data/spec/paperclip/geometry_detector_spec.rb +39 -0
  99. data/{test/geometry_parser_test.rb → spec/paperclip/geometry_parser_spec.rb} +27 -27
  100. data/{test/geometry_test.rb → spec/paperclip/geometry_spec.rb} +50 -52
  101. data/spec/paperclip/glue_spec.rb +44 -0
  102. data/spec/paperclip/has_attached_file_spec.rb +158 -0
  103. data/{test/integration_test.rb → spec/paperclip/integration_spec.rb} +174 -129
  104. data/{test/interpolations_test.rb → spec/paperclip/interpolations_spec.rb} +79 -46
  105. data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
  106. data/{test/io_adapters/attachment_adapter_test.rb → spec/paperclip/io_adapters/attachment_adapter_spec.rb} +33 -32
  107. data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +89 -0
  108. data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
  109. data/{test/io_adapters/file_adapter_test.rb → spec/paperclip/io_adapters/file_adapter_spec.rb} +38 -42
  110. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +138 -0
  111. data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
  112. data/{test/io_adapters/nil_adapter_test.rb → spec/paperclip/io_adapters/nil_adapter_spec.rb} +7 -7
  113. data/{test/io_adapters/registry_test.rb → spec/paperclip/io_adapters/registry_spec.rb} +12 -9
  114. data/{test/io_adapters/stringio_adapter_test.rb → spec/paperclip/io_adapters/stringio_adapter_spec.rb} +21 -18
  115. data/{test/io_adapters/uploaded_file_adapter_test.rb → spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb} +46 -46
  116. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +220 -0
  117. data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
  118. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +109 -0
  119. data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
  120. data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
  121. data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
  122. data/spec/paperclip/meta_class_spec.rb +30 -0
  123. data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
  124. data/spec/paperclip/paperclip_spec.rb +192 -0
  125. data/spec/paperclip/plural_cache_spec.rb +37 -0
  126. data/spec/paperclip/processor_helpers_spec.rb +57 -0
  127. data/{test/processor_test.rb → spec/paperclip/processor_spec.rb} +7 -7
  128. data/spec/paperclip/rails_environment_spec.rb +33 -0
  129. data/{test/rake_test.rb → spec/paperclip/rake_spec.rb} +15 -15
  130. data/spec/paperclip/schema_spec.rb +248 -0
  131. data/{test/storage/filesystem_test.rb → spec/paperclip/storage/filesystem_spec.rb} +18 -18
  132. data/spec/paperclip/storage/fog_spec.rb +566 -0
  133. data/spec/paperclip/storage/s3_live_spec.rb +188 -0
  134. data/spec/paperclip/storage/s3_spec.rb +1693 -0
  135. data/spec/paperclip/style_spec.rb +254 -0
  136. data/spec/paperclip/tempfile_factory_spec.rb +33 -0
  137. data/spec/paperclip/tempfile_spec.rb +35 -0
  138. data/{test/thumbnail_test.rb → spec/paperclip/thumbnail_spec.rb} +158 -137
  139. data/spec/paperclip/url_generator_spec.rb +221 -0
  140. data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
  141. data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
  142. data/{test/validators/attachment_presence_validator_test.rb → spec/paperclip/validators/attachment_presence_validator_spec.rb} +20 -20
  143. data/{test/validators/attachment_size_validator_test.rb → spec/paperclip/validators/attachment_size_validator_spec.rb} +77 -64
  144. data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
  145. data/spec/paperclip/validators_spec.rb +164 -0
  146. data/spec/spec_helper.rb +46 -0
  147. data/spec/support/assertions.rb +82 -0
  148. data/spec/support/fake_model.rb +25 -0
  149. data/spec/support/fake_rails.rb +12 -0
  150. data/spec/support/fixtures/empty.html +1 -0
  151. data/spec/support/fixtures/empty.xlsx +0 -0
  152. data/spec/support/fixtures/spaced file.jpg +0 -0
  153. data/spec/support/matchers/accept.rb +5 -0
  154. data/spec/support/matchers/exist.rb +5 -0
  155. data/spec/support/matchers/have_column.rb +23 -0
  156. data/{test → spec}/support/mock_attachment.rb +2 -0
  157. data/{test → spec}/support/mock_url_generator_builder.rb +2 -2
  158. data/spec/support/model_reconstruction.rb +68 -0
  159. data/spec/support/reporting.rb +11 -0
  160. data/spec/support/test_data.rb +13 -0
  161. data/spec/support/version_helper.rb +9 -0
  162. metadata +344 -226
  163. data/RUNNING_TESTS.md +0 -4
  164. data/cucumber/paperclip_steps.rb +0 -6
  165. data/gemfiles/3.0.gemfile +0 -11
  166. data/gemfiles/3.1.gemfile +0 -11
  167. data/gemfiles/3.2.gemfile +0 -11
  168. data/gemfiles/4.0.gemfile +0 -11
  169. data/test/attachment_definitions_test.rb +0 -12
  170. data/test/attachment_registry_test.rb +0 -88
  171. data/test/file_command_content_type_detector_test.rb +0 -27
  172. data/test/filename_cleaner_test.rb +0 -14
  173. data/test/generator_test.rb +0 -84
  174. data/test/geometry_detector_test.rb +0 -24
  175. data/test/has_attached_file_test.rb +0 -125
  176. data/test/helper.rb +0 -232
  177. data/test/io_adapters/abstract_adapter_test.rb +0 -58
  178. data/test/io_adapters/data_uri_adapter_test.rb +0 -74
  179. data/test/io_adapters/empty_string_adapter_test.rb +0 -18
  180. data/test/io_adapters/http_url_proxy_adapter_test.rb +0 -102
  181. data/test/io_adapters/identity_adapter_test.rb +0 -8
  182. data/test/io_adapters/uri_adapter_test.rb +0 -102
  183. data/test/matchers/have_attached_file_matcher_test.rb +0 -24
  184. data/test/matchers/validate_attachment_content_type_matcher_test.rb +0 -110
  185. data/test/matchers/validate_attachment_presence_matcher_test.rb +0 -69
  186. data/test/matchers/validate_attachment_size_matcher_test.rb +0 -86
  187. data/test/meta_class_test.rb +0 -32
  188. data/test/paperclip_missing_attachment_styles_test.rb +0 -90
  189. data/test/paperclip_test.rb +0 -217
  190. data/test/plural_cache_test.rb +0 -36
  191. data/test/schema_test.rb +0 -200
  192. data/test/storage/fog_test.rb +0 -473
  193. data/test/storage/s3_live_test.rb +0 -179
  194. data/test/storage/s3_test.rb +0 -1356
  195. data/test/style_test.rb +0 -213
  196. data/test/support/mock_model.rb +0 -2
  197. data/test/tempfile_factory_test.rb +0 -17
  198. data/test/url_generator_test.rb +0 -187
  199. data/test/validators/attachment_content_type_validator_test.rb +0 -324
  200. data/test/validators_test.rb +0 -61
  201. /data/{test → spec}/database.yml +0 -0
  202. /data/{test → spec/support}/fixtures/12k.png +0 -0
  203. /data/{test → spec/support}/fixtures/50x50.png +0 -0
  204. /data/{test → spec/support}/fixtures/5k.png +0 -0
  205. /data/{test → spec/support}/fixtures/animated +0 -0
  206. /data/{test → spec/support}/fixtures/animated.gif +0 -0
  207. /data/{test → spec/support}/fixtures/animated.unknown +0 -0
  208. /data/{test → spec/support}/fixtures/bad.png +0 -0
  209. /data/{test → spec/support}/fixtures/fog.yml +0 -0
  210. /data/{test → spec/support}/fixtures/rotated.jpg +0 -0
  211. /data/{test → spec/support}/fixtures/s3.yml +0 -0
  212. /data/{test → spec/support}/fixtures/spaced file.png +0 -0
  213. /data/{test → spec/support}/fixtures/text.txt +0 -0
  214. /data/{test → spec/support}/fixtures/twopage.pdf +0 -0
  215. /data/{test → spec/support}/fixtures/uppercase.PNG +0 -0
  216. /data/{test → spec}/support/mock_interpolator.rb +0 -0
data/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ inherit_from: .hound.yml
data/.travis.yml CHANGED
@@ -1,28 +1,25 @@
1
+ language: ruby
2
+ sudo: false
3
+
1
4
  rvm:
2
- - 1.9.2
3
- - 1.9.3
4
- - jruby-19mode
5
- - rbx-19mode
6
- - 2.0.0
7
- - 2.1.0
5
+ - 2.1
6
+ - 2.2
7
+ - 2.3
8
+ - 2.4
8
9
 
9
- install:
10
- - "bundle install"
10
+ script: "bundle exec rake clean spec cucumber"
11
11
 
12
- before_script: "sudo ntpdate -ub ntp.ubuntu.com pool.ntp.org; true"
13
- script: "bundle exec rake clean test cucumber"
12
+ addons:
13
+ apt:
14
+ packages:
15
+ - ghostscript
14
16
 
15
17
  gemfile:
16
- - gemfiles/3.0.gemfile
17
- - gemfiles/3.1.gemfile
18
- - gemfiles/3.2.gemfile
19
- - gemfiles/4.0.gemfile
18
+ - gemfiles/4.2.gemfile
19
+ - gemfiles/5.0.gemfile
20
20
 
21
21
  matrix:
22
- allow_failures:
23
- - rvm: jruby-19mode
24
- - rvm: rbx-19mode
25
-
22
+ fast_finish: true
26
23
  exclude:
27
- - rvm: 1.9.2
28
- gemfile: gemfiles/4.0.gemfile
24
+ - gemfile: gemfiles/5.0.gemfile
25
+ rvm: 2.1
data/Appraisals CHANGED
@@ -1,19 +1,7 @@
1
- appraise "3.0" do
2
- gem "rails", "~> 3.0.20"
3
- gem "paperclip", :path => "../"
1
+ appraise "4.2" do
2
+ gem "rails", "~> 4.2.0"
4
3
  end
5
4
 
6
- appraise "3.1" do
7
- gem "rails", "~> 3.1.12"
8
- gem "paperclip", :path => "../"
9
- end
10
-
11
- appraise "3.2" do
12
- gem "rails", "~> 3.2.15"
13
- gem "paperclip", :path => "../"
14
- end
15
-
16
- appraise "4.0" do
17
- gem "rails", "~> 4.0.0"
18
- gem "paperclip", :path => "../"
5
+ appraise "5.0" do
6
+ gem "rails", "~> 5.0.0"
19
7
  end
data/CONTRIBUTING.md CHANGED
@@ -1,24 +1,36 @@
1
1
  Contributing
2
2
  ============
3
3
 
4
- We love pull requests. Here's a quick guide:
4
+ We love pull requests from everyone. By participating in this project, you agree
5
+ to abide by the thoughtbot [code of conduct].
6
+
7
+ [code of conduct]: https://thoughtbot.com/open-source-code-of-conduct
8
+
9
+ Here's a quick guide for contributing:
5
10
 
6
11
  1. Fork the repo.
7
12
 
8
- 2. Run the tests. We only take pull requests with passing tests, and it's great
9
- to know that you have a clean slate: `bundle && rake`
13
+ 1. Make sure you have ImageMagick and Ghostscript installed. See [this section]
14
+ (./README.md#image-processor) of the README.
15
+
16
+ 1. Run the tests. We only take pull requests with passing tests, and it's great
17
+ to know that you have a clean slate: `bundle && bundle exec rake`
10
18
 
11
- 3. Add a test for your change. Only refactoring and documentation changes
19
+ 1. Add a test for your change. Only refactoring and documentation changes
12
20
  require no new tests. If you are adding functionality or fixing a bug, we need
13
21
  a test!
14
22
 
15
- 4. Make the test pass.
23
+ 1. Make the test pass.
16
24
 
17
- 5. Push to your fork and submit a pull request.
25
+ 1. Mention how your changes affect the project to other developers and users in
26
+ the `NEWS.md` file.
27
+
28
+ 1. Push to your fork and submit a pull request.
18
29
 
19
30
  At this point you're waiting on us. We like to at least comment on, if not
20
- accept, pull requests within three business days (and, typically, one business
21
- day). We may suggest some changes or improvements or alternatives.
31
+ accept, pull requests within seven business days (most of the work on Paperclip
32
+ gets done on Fridays). We may suggest some changes or improvements or
33
+ alternatives.
22
34
 
23
35
  Some things that will increase the chance that your pull request is accepted,
24
36
  taken straight from the Ruby on Rails guide:
@@ -35,27 +47,31 @@ Paperclip uses [Appraisal](https://github.com/thoughtbot/appraisal) to aid
35
47
  testing against multiple version of Ruby on Rails. This helps us to make sure
36
48
  that Paperclip performs correctly with them.
37
49
 
50
+ Paperclip also uses [RSpec](http://rspec.info) for its unit tests. If you submit
51
+ tests that are not written for Cucumber or RSpec without a very good reason, you
52
+ will be asked to rewrite them before we'll accept.
53
+
38
54
  ### Bootstrapping your test suite:
39
55
 
40
56
  bundle install
41
- bundle exec rake appraisal:install
57
+ bundle exec appraisal install
42
58
 
43
59
  This will install all the required gems that requires to test against each
44
60
  version of Rails, which defined in `gemfiles/*.gemfile`.
45
61
 
46
62
  ### To run a full test suite:
47
63
 
48
- bundle exec rake
64
+ bundle exec appraisal rake
49
65
 
50
- This will run Test::Unit and Cucumber against all version of Rails
66
+ This will run RSpec and Cucumber against all version of Rails
51
67
 
52
68
  ### To run single Test::Unit or Cucumber test
53
69
 
54
70
  You need to specify a `BUNDLE_GEMFILE` pointing to the gemfile before running
55
71
  the normal test command:
56
72
 
57
- BUNDLE_GEMFILE=gemfiles/3.2.gemfile ruby -Itest test/schema_test.rb
58
- BUNDLE_GEMFILE=gemfiles/3.2.gemfile cucumber features/basic_integration.feature
73
+ BUNDLE_GEMFILE=gemfiles/4.1.gemfile rspec spec/paperclip/attachment_spec.rb
74
+ BUNDLE_GEMFILE=gemfiles/4.1.gemfile cucumber features/basic_integration.feature
59
75
 
60
76
  Syntax
61
77
  ------
data/Gemfile CHANGED
@@ -2,7 +2,15 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'jruby-openssl', :platform => :jruby
6
- gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
5
+ gem 'sqlite3', '~> 1.3.8', :platforms => :ruby
6
+ gem 'pry'
7
7
 
8
- gem 'pry', :platform => :ruby
8
+ # Hinting at development dependencies
9
+ # Prevents bundler from taking a long-time to resolve
10
+ group :development, :test do
11
+ gem 'activerecord-import'
12
+ gem 'mime-types'
13
+ gem 'builder'
14
+ gem 'rubocop', require: false
15
+ gem 'rspec'
16
+ end
data/LICENSE CHANGED
@@ -3,7 +3,7 @@ LICENSE
3
3
 
4
4
  The MIT License
5
5
 
6
- Copyright (c) 2008-2013 Jon Yurek and thoughtbot, inc.
6
+ Copyright (c) 2008-2016 Jon Yurek and thoughtbot, inc.
7
7
 
8
8
  Permission is hereby granted, free of charge, to any person obtaining a copy
9
9
  of this software and associated documentation files (the "Software"), to deal
@@ -22,5 +22,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
22
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
23
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
24
  THE SOFTWARE.
25
-
26
-
data/MIGRATING-ES.md ADDED
@@ -0,0 +1,317 @@
1
+ # Migrando de Paperclip a ActiveStorage
2
+
3
+ Paperclip y ActiveStorage resuelven problemas similares con soluciones
4
+ similares, por lo que pasar de uno a otro es simple.
5
+
6
+ El proceso de ir desde Paperclip hacia ActiveStorage es como sigue:
7
+
8
+ 1. Implementa las migraciones a la base de datos de ActiveStorage.
9
+ 2. Configura el almacenamiento.
10
+ 3. Copia la base de datos.
11
+ 4. Copia los archivos.
12
+ 5. Actualiza tus pruebas.
13
+ 6. Actualiza tus vistas.
14
+ 7. Actualiza tus controladores.
15
+ 8. Actualiza tus modelos.
16
+
17
+ ## Implementa las migraciones a la base de datos de ActiveStorage
18
+
19
+ Sigue [las instrucciones para instalar ActiveStorage]. Muy probablemente vas a
20
+ querer agregar la gema `mini_magick` a tu Gemfile.
21
+
22
+
23
+ ```sh
24
+ rails active_storage:install
25
+ ```
26
+
27
+ [las instrucciones para instalar ActiveStorage]: https://github.com/rails/rails/blob/master/activestorage/README.md#installation
28
+
29
+ ## Configura el almacenamiento
30
+
31
+ De nuevo, sigue [las instrucciones para configurar ActiveStorage].
32
+
33
+ [las instrucciones para configurar ActiveStorage]: http://edgeguides.rubyonrails.org/active_storage_overview.html#setup
34
+
35
+ ## Copia la base de datos.
36
+
37
+ Las tablas `active_storage_blobs` y`active_storage_attachments` son en donde
38
+ ActiveStorage espera encontrar los metadatos del archivo. Paperclip almacena los
39
+ metadatos del archivo directamente en en la tabla del objeto asociado.
40
+
41
+ Vas a necesitar escribir una migración para esta conversión. Proveer un script
42
+ simple, es complicado porque están involucrados tus modelos. ¡Pero lo
43
+ intentaremos!
44
+
45
+ Así sería para un `User` con un `avatar` en Paperclip:
46
+
47
+ ```ruby
48
+ class User < ApplicationRecord
49
+ has_attached_file :avatar
50
+ end
51
+ ```
52
+
53
+ Tus migraciones de Paperclip producirán una tabla como la siguiente:
54
+
55
+ ```ruby
56
+ create_table "users", force: :cascade do |t|
57
+ t.string "avatar_file_name"
58
+ t.string "avatar_content_type"
59
+ t.integer "avatar_file_size"
60
+ t.datetime "avatar_updated_at"
61
+ end
62
+ ```
63
+
64
+ Y tu la convertirás en estas tablas:
65
+
66
+ ```ruby
67
+ create_table "active_storage_attachments", force: :cascade do |t|
68
+ t.string "name", null: false
69
+ t.string "record_type", null: false
70
+ t.integer "record_id", null: false
71
+ t.integer "blob_id", null: false
72
+ t.datetime "created_at", null: false
73
+ t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
74
+ t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
75
+ end
76
+ ```
77
+
78
+ ```ruby
79
+ create_table "active_storage_blobs", force: :cascade do |t|
80
+ t.string "key", null: false
81
+ t.string "filename", null: false
82
+ t.string "content_type"
83
+ t.text "metadata"
84
+ t.bigint "byte_size", null: false
85
+ t.string "checksum", null: false
86
+ t.datetime "created_at", null: false
87
+ t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
88
+ end
89
+ ```
90
+
91
+ Así que asumiendo que quieres dejar los archivos en el mismo lugar, _esta es tu
92
+ migración_. De otra forma, ve la siguiente sección primero y modifica la
93
+ migración como corresponda.
94
+
95
+ ```ruby
96
+ Dir[Rails.root.join("app/models/**/*.rb")].sort.each { |file| require file }
97
+
98
+ class ConvertToActiveStorage < ActiveRecord::Migration[5.2]
99
+ require 'open-uri'
100
+
101
+ def up
102
+ # postgres
103
+ get_blob_id = 'LASTVAL()'
104
+ # mariadb
105
+ # get_blob_id = 'LAST_INSERT_ID()'
106
+ # sqlite
107
+ # get_blob_id = 'LAST_INSERT_ROWID()'
108
+
109
+ active_storage_blob_statement = ActiveRecord::Base.connection.raw_connection.prepare(<<-SQL)
110
+ INSERT INTO active_storage_blobs (
111
+ key, filename, content_type, metadata, byte_size,
112
+ checksum, created_at
113
+ ) VALUES (?, ?, ?, '{}', ?, ?, ?)
114
+ SQL
115
+
116
+ active_storage_attachment_statement = ActiveRecord::Base.connection.raw_connection.prepare(<<-SQL)
117
+ INSERT INTO active_storage_attachments (
118
+ name, record_type, record_id, blob_id, created_at
119
+ ) VALUES (?, ?, ?, #{get_blob_id}, ?)
120
+ SQL
121
+
122
+ models = ActiveRecord::Base.descendants.reject(&:abstract_class?)
123
+
124
+ transaction do
125
+ models.each do |model|
126
+ attachments = model.column_names.map do |c|
127
+ if c =~ /(.+)_file_name$/
128
+ $1
129
+ end
130
+ end.compact
131
+
132
+ model.find_each.each do |instance|
133
+ attachments.each do |attachment|
134
+ active_storage_blob_statement.execute(
135
+ key(instance, attachment),
136
+ instance.send("#{attachment}_file_name"),
137
+ instance.send("#{attachment}_content_type"),
138
+ instance.send("#{attachment}_file_size"),
139
+ checksum(instance.send(attachment)),
140
+ instance.updated_at.iso8601
141
+ )
142
+
143
+ active_storage_attachment_statement.
144
+ execute(attachment, model.name, instance.id, instance.updated_at.iso8601)
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ active_storage_attachment_statement.close
151
+ active_storage_blob_statement.close
152
+ end
153
+
154
+ def down
155
+ raise ActiveRecord::IrreversibleMigration
156
+ end
157
+
158
+ private
159
+
160
+ def key(instance, attachment)
161
+ SecureRandom.uuid
162
+ # Alternativamente:
163
+ # instance.send("#{attachment}_file_name")
164
+ end
165
+
166
+ def checksum(attachment)
167
+ # archivos locales almacenados en disco:
168
+ url = attachment.path
169
+ Digest::MD5.base64digest(File.read(url))
170
+
171
+ # archivos remotos almacenados en la computadora de alguién más:
172
+ # url = attachment.url
173
+ # Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
174
+ end
175
+ end
176
+ ```
177
+
178
+ ## Copia los archivos
179
+
180
+ La migración de arriba deja los archivos como estaban. Sin embargo,
181
+ los servicios de Paperclip y ActiveStorage utilizan diferentes ubicaciones.
182
+
183
+ Por defecto, Paperclip se ve así:
184
+
185
+ ```
186
+ public/system/users/avatars/000/000/004/original/the-mystery-of-life.png
187
+ ```
188
+
189
+ Y ActiveStorage se ve así:
190
+
191
+ ```
192
+ storage/xM/RX/xMRXuT6nqpoiConJFQJFt6c9
193
+ ```
194
+
195
+ Ese `xMRXuT6nqpoiConJFQJFt6c9` es el valor de `active_storage_blobs.key`. En la
196
+ migración de arriba usamos simplemente el nombre del archivo, pero tal vez
197
+ quieras usar un UUID.
198
+
199
+ Migrando los archivos en un hospedaje externo (S3, Azure Storage, GCS, etc.)
200
+ está fuera del alcance de este documento inicial. Así es como se vería para un
201
+ almacenamiento local:
202
+
203
+ ```ruby
204
+ #!bin/rails runner
205
+
206
+ class ActiveStorageBlob < ActiveRecord::Base
207
+ end
208
+
209
+ class ActiveStorageAttachment < ActiveRecord::Base
210
+ belongs_to :blob, class_name: 'ActiveStorageBlob'
211
+ belongs_to :record, polymorphic: true
212
+ end
213
+
214
+ ActiveStorageAttachment.find_each do |attachment|
215
+ name = attachment.name
216
+
217
+ source = attachment.record.send(name).path
218
+ dest_dir = File.join(
219
+ "storage",
220
+ attachment.blob.key.first(2),
221
+ attachment.blob.key.first(4).last(2))
222
+ dest = File.join(dest_dir, attachment.blob.key)
223
+
224
+ FileUtils.mkdir_p(dest_dir)
225
+ puts "Moving #{source} to #{dest}"
226
+ FileUtils.cp(source, dest)
227
+ end
228
+ ```
229
+
230
+ ## Actualiza tus pruebas
231
+
232
+ En lugar de utilizar `have_attached_file`, será necesario que escribas tu propio
233
+ matcher. Aquí hay un matcher similar _en espíritu_ al que Paperclip provee:
234
+
235
+
236
+ ```ruby
237
+ RSpec::Matchers.define :have_attached_file do |name|
238
+ matches do |record|
239
+ file = record.send(name)
240
+ file.respond_to?(:variant) && file.respond_to?(:attach)
241
+ end
242
+ end
243
+ ```
244
+
245
+ ## Actualiza tus vistas
246
+
247
+ En Paperclip se ven así:
248
+
249
+ ```ruby
250
+ image_tag @user.avatar.url(:medium)
251
+ ```
252
+
253
+ En ActiveStorage se ven así:
254
+
255
+ ```ruby
256
+ image_tag @user.avatar.variant(resize: "250x250")
257
+ ```
258
+
259
+ ## Actualiza tus controladores
260
+
261
+ Esto no debería _requerir_ ningúna actualización. Sin embargo, si te fijas en
262
+ el schema de tu base de datos, notaras un join.
263
+
264
+ Por ejemplo si tu controlador tiene:
265
+
266
+ ```ruby
267
+ def index
268
+ @users = User.all.order(:name)
269
+ end
270
+ ```
271
+
272
+ Y tu vista tiene:
273
+
274
+ ```
275
+ <ul>
276
+ <% @users.each do |user| %>
277
+ <li><%= image_tag user.avatar.variant(resize: "10x10"), alt: user.name %></li>
278
+ <% end %>
279
+ </ul>
280
+ ```
281
+
282
+ Vas a terminar con un n+1, ya que descargas cada archivo adjunto dentro del
283
+ bucle.
284
+
285
+ Así que mientras que el controlador y el modelo funcionarán sin ningún cambio,
286
+ tal vez quieras revisar dos veces tus bucles y agregar `includes` en dónde haga
287
+ falta.
288
+
289
+ ActiveStorage agrega `avatar_attachment` y `avatar_blob` a las relaciones del
290
+ tipo `has-one`, así como `avatar_attachments` y `avatar_blobs` a las relaciones
291
+ de tipo `has-many`:
292
+
293
+ ```ruby
294
+ def index
295
+ @users = User.all.order(:name).includes(:avatar_attachment)
296
+ end
297
+ ```
298
+
299
+ ## Actualiza tus modelos
300
+
301
+ Sigue [la guía sobre cómo adjuntar archivos a los registros]. Por ejemplo, un
302
+ `User` con un `avatar` se representa como:
303
+
304
+ ```ruby
305
+ class User < ApplicationRecord
306
+ has_one_attached :avatar
307
+ end
308
+ ```
309
+
310
+ Cualquier cambio de tamaño se hace en la vista como un `variant`.
311
+
312
+ [la guía sobre cómo adjuntar archivos a los registros]: http://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-files-to-records
313
+
314
+ ## Quita Paperclip
315
+
316
+ Quita la gema de tu `Gemfile` y corre `bundle`. Corre tus pruebas porque ya
317
+ terminaste!