paperclip 4.3.7 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +3 -0
- data/.hound.yml +5 -16
- data/.travis.yml +15 -12
- data/Appraisals +4 -8
- data/CONTRIBUTING.md +16 -5
- data/Gemfile +3 -8
- data/LICENSE +1 -1
- data/MIGRATING-ES.md +317 -0
- data/MIGRATING.md +375 -0
- data/NEWS +126 -31
- data/README.md +264 -156
- data/Rakefile +1 -1
- data/UPGRADING +12 -9
- data/features/basic_integration.feature +3 -2
- data/features/migration.feature +0 -24
- data/features/step_definitions/attachment_steps.rb +14 -14
- data/features/step_definitions/rails_steps.rb +29 -28
- data/features/step_definitions/s3_steps.rb +2 -2
- data/features/support/env.rb +1 -0
- data/features/support/paths.rb +1 -1
- data/features/support/rails.rb +0 -24
- data/gemfiles/4.2.gemfile +3 -5
- data/gemfiles/{3.2.gemfile → 5.0.gemfile} +4 -6
- data/lib/generators/paperclip/paperclip_generator.rb +9 -1
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +1 -1
- data/lib/paperclip.rb +14 -12
- data/lib/paperclip/attachment.rb +44 -20
- data/lib/paperclip/attachment_registry.rb +2 -1
- data/lib/paperclip/callbacks.rb +8 -6
- data/lib/paperclip/content_type_detector.rb +3 -2
- data/lib/paperclip/errors.rb +3 -1
- data/lib/paperclip/file_command_content_type_detector.rb +1 -1
- data/lib/paperclip/filename_cleaner.rb +0 -1
- data/lib/paperclip/geometry_detector_factory.rb +3 -3
- data/lib/paperclip/glue.rb +1 -1
- data/lib/paperclip/has_attached_file.rb +7 -1
- data/lib/paperclip/helpers.rb +15 -11
- data/lib/paperclip/interpolations.rb +7 -2
- data/lib/paperclip/io_adapters/abstract_adapter.rb +31 -4
- data/lib/paperclip/io_adapters/attachment_adapter.rb +17 -6
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +8 -8
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +5 -4
- data/lib/paperclip/io_adapters/file_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +8 -7
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -6
- data/lib/paperclip/io_adapters/nil_adapter.rb +8 -5
- data/lib/paperclip/io_adapters/registry.rb +6 -2
- data/lib/paperclip/io_adapters/stringio_adapter.rb +9 -6
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +10 -6
- data/lib/paperclip/io_adapters/uri_adapter.rb +22 -17
- data/lib/paperclip/logger.rb +1 -1
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
- data/lib/paperclip/media_type_spoof_detector.rb +11 -7
- data/lib/paperclip/processor.rb +15 -6
- data/lib/paperclip/schema.rb +3 -9
- data/lib/paperclip/storage/filesystem.rb +13 -2
- data/lib/paperclip/storage/fog.rb +21 -14
- data/lib/paperclip/storage/s3.rb +81 -61
- data/lib/paperclip/style.rb +0 -1
- data/lib/paperclip/thumbnail.rb +22 -9
- data/lib/paperclip/url_generator.rb +17 -13
- data/lib/paperclip/validators.rb +1 -1
- data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +4 -0
- data/lib/paperclip/version.rb +3 -1
- data/lib/tasks/paperclip.rake +18 -4
- data/paperclip.gemspec +13 -10
- data/spec/paperclip/attachment_processing_spec.rb +2 -5
- data/spec/paperclip/attachment_registry_spec.rb +28 -0
- data/spec/paperclip/attachment_spec.rb +89 -20
- data/spec/paperclip/content_type_detector_spec.rb +1 -1
- data/spec/paperclip/file_command_content_type_detector_spec.rb +15 -1
- data/spec/paperclip/filename_cleaner_spec.rb +0 -1
- data/spec/paperclip/has_attached_file_spec.rb +24 -8
- data/spec/paperclip/integration_spec.rb +42 -5
- data/spec/paperclip/interpolations_spec.rb +9 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +104 -22
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +6 -3
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +7 -1
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +2 -2
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +47 -13
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/registry_spec.rb +2 -2
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +1 -1
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +5 -5
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +104 -11
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +1 -1
- data/spec/paperclip/media_type_spoof_detector_spec.rb +41 -0
- data/spec/paperclip/paperclip_spec.rb +15 -45
- data/spec/paperclip/processor_spec.rb +4 -4
- data/spec/paperclip/schema_spec.rb +46 -46
- data/spec/paperclip/storage/fog_spec.rb +31 -0
- data/spec/paperclip/storage/s3_live_spec.rb +20 -14
- data/spec/paperclip/storage/s3_spec.rb +359 -192
- data/spec/paperclip/style_spec.rb +0 -1
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +43 -38
- data/spec/paperclip/url_generator_spec.rb +54 -44
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
- data/spec/paperclip/validators_spec.rb +5 -5
- data/spec/spec_helper.rb +5 -2
- data/spec/support/assertions.rb +12 -1
- data/spec/support/mock_attachment.rb +2 -0
- data/spec/support/mock_url_generator_builder.rb +2 -2
- data/spec/support/model_reconstruction.rb +11 -3
- data/spec/support/reporting.rb +11 -0
- metadata +64 -61
- data/cucumber/paperclip_steps.rb +0 -6
- data/gemfiles/4.1.gemfile +0 -19
- data/lib/paperclip/deprecations.rb +0 -42
- data/lib/paperclip/locales/de.yml +0 -18
- data/lib/paperclip/locales/es.yml +0 -18
- data/lib/paperclip/locales/ja.yml +0 -18
- data/lib/paperclip/locales/pt-BR.yml +0 -18
- data/lib/paperclip/locales/zh-CN.yml +0 -18
- data/lib/paperclip/locales/zh-HK.yml +0 -18
- data/lib/paperclip/locales/zh-TW.yml +0 -18
- data/spec/paperclip/deprecations_spec.rb +0 -65
- data/spec/support/deprecations.rb +0 -9
- data/spec/support/rails_helpers.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 898cd227405301490ff021b70120159d15482f1bcf07357f32bc4f14c92a5a46
|
|
4
|
+
data.tar.gz: 48290676c056a90077da05f9906e8621ab2e8593634606b8bcf8e7beee28ef15
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 589b966a2cdf5ccaafa13faa9fb9298e5501274d282aafb098260ffc5268892828ea3f8ddbe4f5ee8de8dcc365031f417577d69b3320cc558eda6b8917ede710
|
|
7
|
+
data.tar.gz: 1b1559aa80cac274756a923a7b943cc4c50e06d984c362764ceeda86f75d9eae2833428dffa0959eee56984e2034e091fd2811aea30b9e933713bfb0070cb107
|
data/.codeclimate.yml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
## Deprecation notice
|
|
2
|
+
|
|
3
|
+
Paperclip is currently undergoing [deprecation in favor of ActiveStorage](https://github.com/thoughtbot/paperclip/blob/master/MIGRATING.md). Maintainers of this repository will no longer be tending to new issues. We're leaving the issues page open so Paperclip users can still see & search through old issues, and continue existing discussions if they wish.
|
data/.hound.yml
CHANGED
|
@@ -20,7 +20,8 @@ AllCops:
|
|
|
20
20
|
- "db/schema.rb"
|
|
21
21
|
- 'vendor/**/*'
|
|
22
22
|
- 'gemfiles/vendor/**/*'
|
|
23
|
-
|
|
23
|
+
Rails:
|
|
24
|
+
Enabled: false
|
|
24
25
|
DisplayCopNames: false
|
|
25
26
|
StyleGuideCopsOnly: false
|
|
26
27
|
Style/AccessModifierIndentation:
|
|
@@ -434,7 +435,7 @@ Style/TrailingBlankLines:
|
|
|
434
435
|
SupportedStyles:
|
|
435
436
|
- final_newline
|
|
436
437
|
- final_blank_line
|
|
437
|
-
Style/
|
|
438
|
+
Style/TrailingCommaInLiteral:
|
|
438
439
|
Description: Checks for trailing comma in parameter lists and literals.
|
|
439
440
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
|
|
440
441
|
Enabled: false
|
|
@@ -560,11 +561,6 @@ Rails/ActionFilter:
|
|
|
560
561
|
- filter
|
|
561
562
|
Include:
|
|
562
563
|
- app/controllers/**/*.rb
|
|
563
|
-
Rails/DefaultScope:
|
|
564
|
-
Description: Checks if the argument passed to default_scope is a block.
|
|
565
|
-
Enabled: true
|
|
566
|
-
Include:
|
|
567
|
-
- app/models/**/*.rb
|
|
568
564
|
Rails/HasAndBelongsToMany:
|
|
569
565
|
Description: Prefer has_many :through to has_and_belongs_to_many.
|
|
570
566
|
Enabled: true
|
|
@@ -685,10 +681,6 @@ Style/DefWithParentheses:
|
|
|
685
681
|
Description: Use def with parentheses when there are arguments.
|
|
686
682
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#method-parens
|
|
687
683
|
Enabled: true
|
|
688
|
-
Style/DeprecatedHashMethods:
|
|
689
|
-
Description: Checks for use of deprecated Hash methods.
|
|
690
|
-
StyleGuide: https://github.com/bbatsov/ruby-style-guide#hash-key
|
|
691
|
-
Enabled: false
|
|
692
684
|
Style/Documentation:
|
|
693
685
|
Description: Document classes and non-namespace modules.
|
|
694
686
|
Enabled: false
|
|
@@ -840,7 +832,7 @@ Style/SelfAssignment:
|
|
|
840
832
|
used.
|
|
841
833
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#self-assignment
|
|
842
834
|
Enabled: false
|
|
843
|
-
Style/
|
|
835
|
+
Style/SpaceBeforeFirstArg:
|
|
844
836
|
Description: Checks that exactly one space is used between a method name and the
|
|
845
837
|
first argument for method calls without parentheses.
|
|
846
838
|
Enabled: true
|
|
@@ -852,7 +844,7 @@ Style/SpaceAfterComma:
|
|
|
852
844
|
Description: Use spaces after commas.
|
|
853
845
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators
|
|
854
846
|
Enabled: true
|
|
855
|
-
Style/
|
|
847
|
+
Style/SpaceAroundKeyword:
|
|
856
848
|
Description: Use spaces after if/elsif/unless/while/until/case/when.
|
|
857
849
|
Enabled: true
|
|
858
850
|
Style/SpaceAfterMethodName:
|
|
@@ -881,9 +873,6 @@ Style/SpaceAroundOperators:
|
|
|
881
873
|
Description: Use spaces around operators.
|
|
882
874
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#spaces-operators
|
|
883
875
|
Enabled: true
|
|
884
|
-
Style/SpaceBeforeModifierKeyword:
|
|
885
|
-
Description: Put a space before the modifier keyword.
|
|
886
|
-
Enabled: true
|
|
887
876
|
Style/SpaceInsideBrackets:
|
|
888
877
|
Description: No spaces after [ or before ].
|
|
889
878
|
StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-spaces-braces
|
data/.travis.yml
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
sudo: false
|
|
3
|
+
|
|
1
4
|
rvm:
|
|
2
|
-
- 2.0
|
|
3
5
|
- 2.1
|
|
4
|
-
- 2.2
|
|
5
|
-
-
|
|
6
|
-
-
|
|
6
|
+
- 2.2
|
|
7
|
+
- 2.3
|
|
8
|
+
- 2.4
|
|
7
9
|
|
|
8
10
|
script: "bundle exec rake clean spec cucumber"
|
|
9
11
|
|
|
12
|
+
addons:
|
|
13
|
+
apt:
|
|
14
|
+
packages:
|
|
15
|
+
- ghostscript
|
|
16
|
+
|
|
10
17
|
gemfile:
|
|
11
|
-
- gemfiles/3.2.gemfile
|
|
12
|
-
- gemfiles/4.1.gemfile
|
|
13
18
|
- gemfiles/4.2.gemfile
|
|
19
|
+
- gemfiles/5.0.gemfile
|
|
14
20
|
|
|
15
21
|
matrix:
|
|
16
22
|
fast_finish: true
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
sudo: false
|
|
22
|
-
cache: bundler
|
|
23
|
+
exclude:
|
|
24
|
+
- gemfile: gemfiles/5.0.gemfile
|
|
25
|
+
rvm: 2.1
|
data/Appraisals
CHANGED
data/CONTRIBUTING.md
CHANGED
|
@@ -1,20 +1,31 @@
|
|
|
1
1
|
Contributing
|
|
2
2
|
============
|
|
3
3
|
|
|
4
|
-
We love pull requests.
|
|
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
|
-
|
|
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
|
|
9
17
|
to know that you have a clean slate: `bundle && bundle exec rake`
|
|
10
18
|
|
|
11
|
-
|
|
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
|
-
|
|
23
|
+
1. Make the test pass.
|
|
24
|
+
|
|
25
|
+
1. Mention how your changes affect the project to other developers and users in
|
|
26
|
+
the `NEWS.md` file.
|
|
16
27
|
|
|
17
|
-
|
|
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
31
|
accept, pull requests within seven business days (most of the work on Paperclip
|
data/Gemfile
CHANGED
|
@@ -3,19 +3,14 @@ source "https://rubygems.org"
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
5
|
gem 'sqlite3', '~> 1.3.8', :platforms => :ruby
|
|
6
|
-
|
|
7
|
-
gem 'jruby-openssl', :platforms => :jruby
|
|
8
|
-
gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
|
|
9
|
-
|
|
10
|
-
gem 'rubysl', :platforms => :rbx
|
|
11
|
-
gem 'racc', :platforms => :rbx
|
|
12
|
-
|
|
13
6
|
gem 'pry'
|
|
14
7
|
|
|
15
8
|
# Hinting at development dependencies
|
|
16
9
|
# Prevents bundler from taking a long-time to resolve
|
|
17
10
|
group :development, :test do
|
|
18
|
-
gem '
|
|
11
|
+
gem 'activerecord-import'
|
|
12
|
+
gem 'mime-types'
|
|
19
13
|
gem 'builder'
|
|
20
14
|
gem 'rubocop', require: false
|
|
15
|
+
gem 'rspec'
|
|
21
16
|
end
|
data/LICENSE
CHANGED
|
@@ -3,7 +3,7 @@ LICENSE
|
|
|
3
3
|
|
|
4
4
|
The MIT License
|
|
5
5
|
|
|
6
|
-
Copyright (c) 2008-
|
|
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
|
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!
|