Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
paperclip
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ikcrm_common
paperclip
Commits
3f1512fd
Unverified
Commit
3f1512fd
authored
May 14, 2018
by
Horacio Chávez
Committed by
Mike Burns
May 18, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Spanish translation to MIGRATING
parent
9e40a5d5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
317 additions
and
0 deletions
+317
-0
MIGRATING-ES.md
+317
-0
No files found.
MIGRATING-ES.md
0 → 100644
View file @
3f1512fd
# Migrando de Paperclip a ActiveStorage
Paperclip y ActiveStorage resuelven problemas similares con soluciones
similares, por lo que pasar de uno a otro es simple.
El proceso de ir desde Paperclip hacia ActiveStorage es como sigue:
1.
Implementa las migraciones a la base de datos de ActiveStorage.
2.
Configura el almacenamiento.
3.
Copia la base de datos.
4.
Copia los archivos.
5.
Actualiza tus pruebas.
6.
Actualiza tus vistas.
7.
Actualiza tus controladores.
8.
Actualiza tus modelos.
## Implementa las migraciones a la base de datos de ActiveStorage
Sigue
[
las instrucciones para instalar ActiveStorage
]
. Muy probablemente vas a
querer agregar la gema
`mini_magick`
a tu Gemfile.
```sh
rails active_storage:install
```
[
las instrucciones para instalar ActiveStorage
]:
https://github.com/rails/rails/blob/master/activestorage/README.md#installation
## Configura el almacenamiento
De nuevo, sigue
[
las instrucciones para configurar ActiveStorage
]
.
[
las instrucciones para configurar ActiveStorage
]:
http://edgeguides.rubyonrails.org/active_storage_overview.html#setup
## Copia la base de datos.
Las tablas
`active_storage_blobs`
y
`active_storage_attachments`
son en donde
ActiveStorage espera encontrar los metadatos del archivo. Paperclip almacena los
metadatos del archivo directamente en en la tabla del objeto asociado.
Vas a necesitar escribir una migración para esta conversión. Proveer un script
simple, es complicado porque están involucrados tus modelos. ¡Pero lo
intentaremos!
Así sería para un
`User`
con un
`avatar`
en Paperclip:
```
ruby
class
User
<
ApplicationRecord
has_attached_file
:avatar
end
```
Tus migraciones de Paperclip producirán una tabla como la siguiente:
```
ruby
create_table
"users"
,
force: :cascade
do
|
t
|
t
.
string
"avatar_file_name"
t
.
string
"avatar_content_type"
t
.
integer
"avatar_file_size"
t
.
datetime
"avatar_updated_at"
end
```
Y tu la convertirás en estas tablas:
```
ruby
create_table
"active_storage_attachments"
,
force: :cascade
do
|
t
|
t
.
string
"name"
,
null:
false
t
.
string
"record_type"
,
null:
false
t
.
integer
"record_id"
,
null:
false
t
.
integer
"blob_id"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
index
[
"blob_id"
],
name:
"index_active_storage_attachments_on_blob_id"
t
.
index
[
"record_type"
,
"record_id"
,
"name"
,
"blob_id"
],
name:
"index_active_storage_attachments_uniqueness"
,
unique:
true
end
```
```
ruby
create_table
"active_storage_blobs"
,
force: :cascade
do
|
t
|
t
.
string
"key"
,
null:
false
t
.
string
"filename"
,
null:
false
t
.
string
"content_type"
t
.
text
"metadata"
t
.
bigint
"byte_size"
,
null:
false
t
.
string
"checksum"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
index
[
"key"
],
name:
"index_active_storage_blobs_on_key"
,
unique:
true
end
```
Así que asumiendo que quieres dejar los archivos en el mismo lugar, _esta es tu
migración_. De otra forma, ve la siguiente sección primero y modifica la
migración como corresponda.
```
ruby
Dir
[
Rails
.
root
.
join
(
"app/models/**/*.rb"
)].
sort
.
each
{
|
file
|
require
file
}
class
ConvertToActiveStorage
<
ActiveRecord
::
Migration
[
5.2
]
require
'open-uri'
def
up
# postgres
get_blob_id
=
'LASTVAL()'
# mariadb
# get_blob_id = 'LAST_INSERT_ID()'
# sqlite
# get_blob_id = 'LAST_INSERT_ROWID()'
active_storage_blob_statement
=
ActiveRecord
::
Base
.
connection
.
raw_connection
.
prepare
(
<<-
SQL
)
INSERT INTO active_storage_blobs (
key, filename, content_type, metadata, byte_size,
checksum, created_at
) VALUES (?, ?, ?, '{}', ?, ?, ?)
SQL
active_storage_attachment_statement
=
ActiveRecord
::
Base
.
connection
.
raw_connection
.
prepare
(
<<-
SQL
)
INSERT INTO active_storage_attachments (
name, record_type, record_id, blob_id, created_at
) VALUES (?, ?, ?,
#{
get_blob_id
}
, ?)
SQL
models
=
ActiveRecord
::
Base
.
descendants
.
reject
(
&
:abstract_class?
)
transaction
do
models
.
each
do
|
model
|
attachments
=
model
.
column_names
.
map
do
|
c
|
if
c
=~
/(.+)_file_name$/
$1
end
end
.
compact
model
.
find_each
.
each
do
|
instance
|
attachments
.
each
do
|
attachment
|
active_storage_blob_statement
.
execute
(
key
(
instance
,
attachment
),
instance
.
send
(
"
#{
attachment
}
_file_name"
),
instance
.
send
(
"
#{
attachment
}
_content_type"
),
instance
.
send
(
"
#{
attachment
}
_file_size"
),
checksum
(
instance
.
send
(
attachment
)),
instance
.
updated_at
.
iso8601
)
active_storage_attachment_statement
.
execute
(
attachment
,
model
.
name
,
instance
.
id
,
instance
.
updated_at
.
iso8601
)
end
end
end
end
active_storage_attachment_statement
.
close
active_storage_blob_statement
.
close
end
def
down
raise
ActiveRecord
::
IrreversibleMigration
end
private
def
key
(
instance
,
attachment
)
SecureRandom
.
uuid
# Alternativamente:
# instance.send("#{attachment}_file_name")
end
def
checksum
(
attachment
)
# archivos locales almacenados en disco:
url
=
attachment
.
path
Digest
::
MD5
.
base64digest
(
File
.
read
(
url
))
# archivos remotos almacenados en la computadora de alguién más:
# url = attachment.url
# Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
end
end
```
## Copia los archivos
La migración de arriba deja los archivos como estaban. Sin embargo,
los servicios de Paperclip y ActiveStorage utilizan diferentes ubicaciones.
Por defecto, Paperclip se ve así:
```
public/system/users/avatars/000/000/004/original/the-mystery-of-life.png
```
Y ActiveStorage se ve así:
```
storage/xM/RX/xMRXuT6nqpoiConJFQJFt6c9
```
Ese
`xMRXuT6nqpoiConJFQJFt6c9`
es el valor de
`active_storage_blobs.key`
. En la
migración de arriba usamos simplemente el nombre del archivo, pero tal vez
quieras usar un UUID.
Migrando los archivos en un hospedaje externo (S3, Azure Storage, GCS, etc.)
está fuera del alcance de este documento inicial. Así es como se vería para un
almacenamiento local:
```
ruby
#!bin/rails runner
class
ActiveStorageBlob
<
ActiveRecord
::
Base
end
class
ActiveStorageAttachment
<
ActiveRecord
::
Base
belongs_to
:blob
,
class_name:
'ActiveStorageBlob'
belongs_to
:record
,
polymorphic:
true
end
ActiveStorageAttachment
.
find_each
do
|
attachment
|
name
=
attachment
.
name
source
=
attachment
.
record
.
send
(
name
).
path
dest_dir
=
File
.
join
(
"storage"
,
attachment
.
blob
.
key
.
first
(
2
),
attachment
.
blob
.
key
.
first
(
4
).
last
(
2
))
dest
=
File
.
join
(
dest_dir
,
attachment
.
blob
.
key
)
FileUtils
.
mkdir_p
(
dest_dir
)
puts
"Moving
#{
source
}
to
#{
dest
}
"
FileUtils
.
cp
(
source
,
dest
)
end
```
## Actualiza tus pruebas
En lugar de utilizar
`have_attached_file`
, será necesario que escribas tu propio
matcher. Aquí hay un matcher similar _en espíritu_ al que Paperclip provee:
```ruby
RSpec::Matchers.define :have_attached_file do |name|
matches do |record|
file = record.send(name)
file.respond_to?(:variant) && file.respond_to?(:attach)
end
end
```
## Actualiza tus vistas
En Paperclip se ven así:
```
ruby
image_tag
@user
.
avatar
.
url
(
:medium
)
```
En ActiveStorage se ven así:
```
ruby
image_tag
@user
.
avatar
.
variant
(
resize:
"250x250"
)
```
## Actualiza tus controladores
Esto no debería _requerir_ ningúna actualización. Sin embargo, si te fijas en
el schema de tu base de datos, notaras un join.
Por ejemplo si tu controlador tiene:
```
ruby
def
index
@users
=
User
.
all
.
order
(
:name
)
end
```
Y tu vista tiene:
```
<ul>
<% @users.each do |user| %>
<li><%= image_tag user.avatar.variant(resize: "10x10"), alt: user.name %></li>
<% end %>
</ul>
```
Vas a terminar con un n+1, ya que descargas cada archivo adjunto dentro del
bucle.
Así que mientras que el controlador y el modelo funcionarán sin ningún cambio,
tal vez quieras revisar dos veces tus bucles y agregar
`includes`
en dónde haga
falta.
ActiveStorage agrega
`avatar_attachment`
y
`avatar_blob`
a las relaciones del
tipo
`has-one`
, así como
`avatar_attachments`
y
`avatar_blobs`
a las relaciones
de tipo
`has-many`
:
```
ruby
def
index
@users
=
User
.
all
.
order
(
:name
).
includes
(
:avatar_attachment
)
end
```
## Actualiza tus modelos
Sigue
[
la guía sobre cómo adjuntar archivos a los registros
]
. Por ejemplo, un
`User`
con un
`avatar`
se representa como:
```
ruby
class
User
<
ApplicationRecord
has_one_attached
:avatar
end
```
Cualquier cambio de tamaño se hace en la vista como un
`variant`
.
[
la guía sobre cómo adjuntar archivos a los registros
]:
http://edgeguides.rubyonrails.org/active_storage_overview.html#attaching-files-to-records
## Quita Paperclip
Quita la gema de tu
`Gemfile`
y corre
`bundle`
. Corre tus pruebas porque ya
terminaste!
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment