Carga de imágenes
Hasta la versión 5.1 de Ruby on Rails, la forma más fácil de implementar carga de imágenes, y de archivos en general, es con alguna gema como CarrierWave, Paperclip o Dragonfly.
Sin embargo, desde la versión 5.2, Ruby on Rails incluye una módulo para cargar archivos llamado ActiveStorage.
En este capítulo vamos a mostrar primero cómo configurar Paperclip, que es quizá la gema más popular. Luego hablaremos de ActiveStorage.
Por defecto Paperclip almacena la imagen de forma local pero más adelante veremos cómo almacenarla en servicios externos.

ImageMagick

Independiente de si utilizas una gema o ActiveStorage vas a necesitar instalar ImageMagick, una herramienta que permite manipular imágenes.
Para instalar ImageMagcik en Ubuntu (or any Debian base Linux distribution) utiliza el siguiente comando:
1
$ sudo apt-get install imagemagick -y
Copied!
En Mac la forma más fácil es a través de Homebrew:
1
$ brew install imagemagick
Copied!
En Windows ... estás por tu cuenta amigo (mentira, queda pendiente esta parte ;)

Paperclip (Rails 5.1 y anterior)

El primer paso es incluir la gema en tu Gemfile:
1
gem "paperclip", "~> 6.0.0"
Copied!
Y ejecutar bundle install.

Uso

Para agregar imágenes a tus modelos debes realizar varios pasos que vamos a ver a continuación.

Agregar los campos al modelo

Para agregar una imagen a un nuevo modelo a través del generador de Rails utiliza el tipo attachment sobre el campo que va a contener la información de la imagen:
1
$ rails generate model product name image:attachment
Copied!
En este ejemplo llamamos el campo image pero lo puedes llamar como quieras. Paperclip genera los siguientes campos en el modelo:
1
image_file_name
2
image_file_size
3
image_content_type
4
image_updated_at
Copied!
Para agregar una imagen a un modelo existente debes ejectuar el siguiente comando (asumiendo que el modelo se llama Product y el campo para la imagen se va a llamar image):
1
$ rails generate paperclip product image
Copied!

Configurando el modelo

En el modelo debes agregar has_attached_file como en el siguiente ejemplo:
1
class Product < ApplicationRecord
2
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }
3
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
4
end
Copied!
En este ejemplo estamos creando dos estilos para la imagen: medium y thumb. Cada estilo tiene unas dimensiones dependiendo del contexto en el que se vaya a mostrar.
Por defecto debemos valirdar el tipo de contenido o, de lo contrario, Paperclip genera un error.

Agregando la imagen al formulario

En el formulario para crear y editar productos debes agregar el campo y asegurarte que el formulario tenga la opción de multipart:
1
<%= form_for @product, html: { multipart: true } do |form| %>
2
<%= form.file_field :image %>
3
<%= form.submit %>
4
<% end %>
Copied!
En el controlador debes permitir el nuevo campo image:
1
def create
2
@product = Product.create(product_params)
3
end
4
5
private
6
def product_params
7
params.require(:product).permit(:image)
8
end
Copied!

Mostrando la imagen en una vista

Para mostrar la imagen utiliza alguna de las siguientes opciones:
1
<%= image_tag @product.image.url %>
2
<%= image_tag @product.image.url(:medium) %>
3
<%= image_tag @product.image.url(:thumb) %>
Copied!
La primera muestra la imagen original y las demás son los estilos que definiste en el modelo.

Verificando si existe la imagen

Existen dos formas de verificar si la imagen existe:
    Utilizando los método file? and present? que verifican si el campo image_file_name (asumiendo que el campo se llama image) está presente.
    Utilizando el método exists? que va a verificar si la imagen existe (si utilizas un servicio externo este método puede tomar un tiempo hasta que hace la petición al servicio).

Eliminando una imagen

Para eliminar una imagen define el campo en nil y guarda el objeto:
1
@product.image = nil
2
@product.save
Copied!

Validaciones

Para validar que la imagen esté presente utiliza:
1
validates_attachment :image, presence: true
Copied!
Para validar el tamaño utiliza:
1
validates_attachment :image, size: { less_than: 1.megabytes }
Copied!
Por último, puedes unir todas las validaciones (incluyendo la del tipo de contenido) en una sola validación:
1
validates_attachment :image, presence: true,
2
content_type: { content_type: /\Aimage\/.*\z/ },
3
size: { in: 0..10.kilobytes }
Copied!

Almacenamiento

Por defecto Paperclip viene con 3 adaptadores de almacenamiento:
    Archivo. Es el adaptador por defecto que almacena la imagen localmente en la carpeta public/system/ de la aplicación.
    Amazon S3
    Fog
También puedes usar Dropbox a través de la gema paperclip-dropbox.
En esta sección vamos a ver la configuración en Amazon S3, que es una de las más populares. Para eso vas a necesitar una cuenta en AWS y crear un bucket (un directorio) en S3 (región "us-east-1") antes de continuar.
El primer paso es configurar la gema en el Gemfile:
1
gem 'aws-sdk-s3', '~> 1.9', '>= 1.9.1'
Copied!
Luego, en config/environments/development.rb, antes del último end agrega la siguiente configuración:
1
config.paperclip_defaults = {
2
storage: :s3,
3
s3_credentials: {
4
bucket: "<nombre_del_bucket>",
5
preserve_files: true,
6
s3_region: "us-east-1"
7
}
8
}
Copied!
Nota: Si quieres configurar Amazon S3 en producción modificarías config/environments/production.rb.
Por último, crea un archivo config/initializers/aws.rb con el siguiente contenido reemplazando los valores que están entre < y >:
1
Aws.config.update({
2
credentials: Aws::Credentials.new("<AWS_ACCESS_KEY_ID>", "<AWS_SECRET_ACCESS_KEY>")
3
})
Copied!
Una recomendación es utilizar la gema Figaro para utilizar variables de entorno.

ActiveStorage (Rails 5.2 y superior)

El primer paso para utilizar ActiveStorage es ejecutar los siguientes comandos:
1
$ rails active_storage:install
2
$ rails db:migrate
Copied!
Esos comandos crean dos tablas: active_storage_blobs and active_storage_attachments.

Configurando el modelo

Para asociar un archivo a un modelo utilizamos has_one_attached seguido del nombre que le queremos dar a nuestro archivo. Por ejemplo:
1
class Report < ApplicationRecord
2
has_one_attached :screenshot
3
end
Copied!
Si queremos asociar varios archivos utilizamos has_many_attached:
1
class Product < ApplicationRecord
2
has_many_attached :images
3
end
Copied!

Agregando la imagen al formulario

En el formulario para crear y editar productos debes agregar el campo y asegurarte que el formulario tenga la opción de multipart:
1
<%= form_for @product, html: { multipart: true } do |form| %>
2
<%= form.file_field :image %>
3
<%= form.submit %>
4
<% end %>
Copied!
En el controlador debes permitir el nuevo campo image:
1
def create
2
@product = Product.create(product_params)
3
end
4
5
private
6
def product_params
7
params.require(:product).permit(:image)
8
end
Copied!

Mostrando la imagen en una vista

Para mostar la imagen utilizamos el método preview:
1
<%= image_tag product.image.preview(resize_to_limit: [100, 100]) %>
Copied!

Verificando si existe una imagen

Para determinar si una imagen existe utiliza el método attached?:
1
product.image.attached?
Copied!

Eliminando una imagen

Para eliminar una imagen de un modelo utiliza el método purge:
1
product.image.purge
Copied!

Validaciones

ActiveStorage no incluye validaciones para las imágenes, así que debemos implementar nuestra propia validación. Por ejemplo, para validar que un archivo exista y sea una imagen utilizaríamos el siguiente código:
1
class Product < ApplicationRecord
2
has_one_attached :image
3
4
validate :image_validator
5
6
private
7
def image_validator
8
if !image.attached?
9
errors.add(:image, "is required")
10
elsif image.content_type.in?(%w(image/png image/jpeg))
11
errors.add(:image, 'must be an image')
12
end
13
end
14
end
Copied!

Almacenamiento

Por defecto ActiveStorage almacena la información localmente en una carpeta de tu computador. Sin embargo, al igual que con Paperclip, esto es configurable para cada uno de los ambientes (desarrollo, producción y pruebas).
Para usar Amazon S3 vas a necesitar una cuenta en AWS y crear un bucket (un directorio) en S3 (región "us-east-1") antes de continuar.
El primer paso es configurar el servicio en el archivo config/storage.yml:
1
amazon:
2
service: S3
3
access_key_id: <%= ENV['aws_key']%>
4
secret_access_key: <%= ENV['aws_secret'] %>
5
region: us-east-1
6
bucket: <nombre_del_bucket>
Copied!
Nota: estamos utilizando variables de entorno para almacenar las llaves de AWS.
Ahora, en la carpeta config/environments/ ubica el ambiente para el que deseas configurar AWS (development.rb o production.rb) y modifica la opción config.active_storage.service con el valor :amazon:
1
config.active_storage.service = :amazon
Copied!
Por último, no olvides agregar la siguiente línea al Gemfile:
1
gem "aws-sdk-s3", require: false
Copied!
Y ejecutar bundle install.
Last modified 3yr ago