Este es otro artículo de la serie "Cargar con rieles". Hoy vamos a conocer a Carrierwave, una de las soluciones de carga de archivos más populares para Rails. Me gusta Carrierwave porque es fácil de comenzar, tiene muchas características listas para usar y proporciona docenas de artículos de "cómo hacer" escritos por los miembros de la comunidad, para que no te pierdas..
En este artículo, aprenderás cómo:
El código fuente de este artículo está disponible en GitHub. Disfruta leyendo!
Como siempre, comience creando una nueva aplicación de Rails:
raíles nuevos UploadingWithCarrierwave -T
Para esta demo usaré Rails 5.0.2. Ten en cuenta que Carrierwave 1 solo admite Rails 4+ y Ruby 2. Si aún viajas en Rails 3, conecta la versión 0.11 de Carrierwave.
Para ver Carrierwave en acción, vamos a crear una aplicación de blog muy simple con una única Enviar
modelo. Tendrá los siguientes atributos principales:
título
(cuerda
)cuerpo
(texto
)imagen
(cuerda
): este campo contendrá una imagen (el nombre de un archivo, para ser preciso) adjunta a la publicaciónGenerar y aplicar una nueva migración:
rieles modelo g Título de la publicación: cuerpo de la cadena: imagen de texto: cadena rieles db: migrar
Configurar algunas rutas:
recursos: raíz de publicaciones a: 'entradas # índice'
Además, crea un controlador muy básico:
clase PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update] def index @posts = Post.order('created_at DESC') end def show end def new @post = Post.new end def create @post = Post.new(post_params) if @post.save redirect_to posts_path else render :new end end def edit end def update if @post.update_attributes(post_params) redirect_to post_path(@post) else render :edit end end private def post_params params.require(:post).permit(:title, :body, :image) end def set_post @post = Post.find(params[:id]) end end
Ahora elaboremos el índice ver:
Mensajes
<%= link_to 'Add post', new_post_path %> <%= render @posts %>
Y el correspondiente parcial:
<%= link_to post.title, post_path(post) %>
<%= truncate(post.body, length: 150) %>
<%= link_to 'Edit', edit_post_path(post) %>
Aquí estoy usando los rieles truncar
Método para mostrar solo los primeros 150 símbolos de la publicación. Antes de crear otras vistas y un formulario parcial, primero integremos Carrierwave en la aplicación.
Caer en una nueva joya en el Gemfile:
gema 'carrierwave', '~> 1.0'
Correr:
instalación de paquete
Carrierwave almacena su configuración en el interior. cargadores que se incluyen en sus modelos. Para generar un cargador, use el siguiente comando:
Los carriles generan la imagen del cargador.
Ahora dentro aplicación / cargadores, encontrarás un nuevo archivo llamado image_uploader.rb. Tenga en cuenta que tiene algunos comentarios y ejemplos útiles, por lo que puede usarlo para comenzar. En esta demostración usaremos ActiveRecord, pero Carrierwave también tiene soporte para Mongoid, Sequel y DataMapper..
A continuación, debemos incluir o montar este cargador en el modelo:
mount_uploader: image, ImageUploader
El cargador ya tiene una configuración predeterminada sana, pero como mínimo debemos elegir dónde se almacenarán los archivos cargados. Por ahora, vamos a emplear el almacenamiento de archivos:
almacenamiento: archivo
Por defecto, los archivos se colocarán dentro de la public / uploads directorio, por lo que es mejor excluirlo del sistema de control de versiones:
public / uploads
También puede modificar el store_dir
Método dentro de su cargador para elegir otra ubicación.
En este punto, podemos crear una nueva vista y un formulario parcial para comenzar a cargar archivos:
Añadir publicación
<%= render 'form', post: @post %>
<%= form_for post do |f| %><%= f.label :title %> <%= f.text_field :title %><%= f.label :body %> <%= f.text_area :body %><%= f.label :image %> <%= f.file_field :image %><%= f.submit %> <% end %>
Tenga en cuenta que el PostsController
no necesita ser modificado ya que ya permitimos la imagen
atributo.
Por último, crea la vista de edición:
Editar post
<%= render 'form', post: @post %>
¡Eso es! Puede iniciar el servidor e intentar crear una publicación con una imagen. El problema es que esta imagen no es visible en ninguna parte, por lo que vamos a la siguiente sección y agregamos una página de presentación.!
Entonces, la única vista que aún no hemos creado es espectáculo. Agrégalo ahora:
<%= link_to 'All posts', posts_path %><%= @post.title %>
<%= image_tag(@post.image.url, alt: 'Image') if @post.image? %><%= @post.body %>
<%= link_to 'Edit', edit_post_path(@post) %>
Como puede ver, mostrar un archivo adjunto es realmente sencillo: todo lo que necesita hacer es decir @ post.image.url
para agarrar la URL de una imagen. Para obtener una ruta al archivo, use la trayectoria de corriente
método. Tenga en cuenta que Carrierwave también proporciona una imagen?
método para que comprobemos si hay algún archivo adjunto (el imagen
El método en sí nunca volverá nulo
, incluso si el archivo no está presente).
Ahora, después de navegar a una publicación, debería ver una imagen, pero puede parecer demasiado grande: después de todo, no estamos restringiendo las dimensiones en ningún lugar. Por supuesto, podríamos haber reducido la imagen con algunas reglas CSS, pero es mucho mejor generar una miniatura después de que el archivo se haya cargado. Esto, sin embargo, requiere algunos pasos adicionales..
Para recortar y escalar imágenes, necesitamos una herramienta separada. Fuera de la caja Carrierwave tiene soporte para gemas RMagick y MiniMagick que, a su vez, se utilizan para manipular imágenes con la ayuda de ImageMagick. ImageMagick es una solución de código abierto que le permite editar imágenes existentes y generar otras nuevas, por lo que antes de continuar, necesita descargarla e instalarla. A continuación, eres libre de elegir cualquiera de las dos gemas. Me quedo con MiniMagick, porque es mucho más fácil de instalar y tiene mejor soporte:
gema 'mini_magick'
Correr:
instalación de paquete
Luego incluye MiniMagick en tu cargador:
incluye CarrierWave :: MiniMagick
Ahora simplemente necesitamos presentar una nueva versión a nuestro cargador. El concepto de versiones (o estilos) se utiliza en muchas bibliotecas de carga de archivos; simplemente significa que los archivos adicionales basados en el archivo adjunto original se crearán, por ejemplo, con diferentes dimensiones o formatos. Introduce una nueva versión llamada pulgar
:
versión: el pulgar procesa resize_to_fill: [350, 350] end
Puede tener tantas versiones como desee y, lo que es más, incluso las versiones se pueden construir sobre otras:
versión: small_thumb, from_version:: thumb hacer procesar resize_to_fill: [20, 20] end
Si ya has subido algunas imágenes, no tendrán miniaturas disponibles. Sin embargo, esto no es un problema, ya que puede volver a crearlos desde la consola de Rails:
rieles c Post.find_each | post | post.image.recreate_versions! (: thumb) si post.image?
Por último, muestre su miniatura con un enlace a la imagen original:
<%= link_to(image_tag(@post.image.thumb.url, alt: 'Image'), @post.image.url, target: '_blank') if @post.image? %>
Arranca el servidor y observa el resultado.!
Actualmente, nuestra carga funciona, pero no estamos validando los comentarios de los usuarios, lo que, por supuesto, es malo. Mientras queramos trabajar solo con imágenes, vamos a agregar a la lista blanca las extensiones .png, .jpg y .gif:
def extension_whitelist% w (jpg jpeg gif png) final
También puede agregar verificaciones de tipo de contenido definiendo un content_type_whitelist
método:
def content_type_whitelist / image \ // end
Alternativamente, es posible incluir en la lista negra algunos tipos de archivos, por ejemplo, ejecutables, definiendo el content_type_blacklist
método.
Además de verificar el tipo y la extensión de un archivo, impongamos que sea inferior a 1 megabyte. Para hacerlo, necesitaremos una gema adicional que admita validaciones de archivos para ActiveModel:
gema 'file_validators'
Instalarlo:
instalación de paquete
Ahora introduzca las validaciones deseadas (tenga en cuenta que también estoy agregando cheques para el título
y cuerpo
atributos):
valida: título, presencia: verdadero, longitud: mínimo: 2 valida: cuerpo, presencia: verdadero valida: imagen, tamaño de archivo: menos_que: 1.megabytes
Lo siguiente que debe hacer es agregar las traducciones de I18n para los mensajes de error de Carrierwave:
es: errores: mensajes: carrierwave_processing_error: "No se puede cambiar el tamaño de la imagen". carrierwave_integrity_error: "No es una imagen". carrierwave_download_error: "No se pudo descargar la imagen". extension_whitelist_error: "No está permitido cargar archivos% extensión, tipos permitidos:% allowed_types" extensión_blacklist_error: "No está permitido cargar archivos% extensión, tipos prohibidos:% prohibido_tipos"
Actualmente, no mostramos errores de validación en ninguna parte, así que vamos a crear un parcial compartido:
<% if object.errors.any? %>Se encontraron algunos errores:
Emplea este parcial dentro del formulario:
<%= render 'shared/errors', object: post %>
Ahora intenta subir algunos archivos inválidos y observa el resultado. Debería funcionar, pero si elige un archivo válido y no completa el título o el cuerpo, las comprobaciones seguirán fallando y se mostrará un error. Sin embargo, el campo de archivo se borrará y el usuario deberá elegir la imagen nuevamente, lo que no es muy conveniente. Para solucionarlo, necesitamos agregar otro campo al formulario..
Persistir archivos a través de la redistribución de formularios es realmente muy fácil. Todo lo que necesita hacer es agregar un nuevo campo oculto y permitirlo dentro del controlador:
<%= f.label :image %> <%= f.file_field :image %>
<%= f.hidden_field :image_cache %>
params.require (: post) .permit (: title,: body,: image,: image_cache)
Ahora el image_cache
se rellenará automáticamente y la imagen no se perderá. También puede ser útil mostrar una miniatura para que el usuario entienda que la imagen se procesó correctamente:
<% if post.image? %> <%= image_tag post.image.thumb.url %> <% end %>
Otra característica muy común es la capacidad de eliminar archivos adjuntos al editar un registro. Con Carrierwave, la implementación de esta característica no es un problema. Agregar una nueva casilla de verificación al formulario:
<% if post.image? %> <%= image_tag post.image.thumb.url %><%= label_tag :remove_image do %> Quita la imagen <%= f.check_box :remove_image %> <% end %><% end %>
Y permitir el quita la imagen
atributo:
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache)
¡Eso es! Para eliminar una imagen manualmente, use la quita la imagen!
método:
@ post.remove_image!
Carrierwave también proporciona una característica muy interesante de inmediato: la capacidad de cargar archivos desde ubicaciones remotas mediante su URL. Introduzcamos esta habilidad ahora agregando un nuevo campo y permitiendo el atributo correspondiente:
<%= f.text_field :remote_image_url %> Introduce la URL de una imagen
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache,: remote_image_url)
¿Cuan genial es eso? No necesita realizar ningún cambio y puede probar esta función de inmediato!
Supongamos que queremos que nuestra publicación tenga varios archivos adjuntos disponibles. Con la configuración actual no es posible, pero afortunadamente, Carrierwave también soporta este escenario. Para implementar esta característica, debe agregar un campo serializado (para SQLite) o un campo JSON (para Postgres o MySQL). Prefiero la última opción, así que vamos a cambiar a un nuevo adaptador de base de datos ahora. Eliminar la gema sqlite3 de la Gemfile y agregue pg en su lugar:
gema 'pg'
Instalarlo:
instalación de paquete
Modificar la configuración de la base de datos de esta manera:
predeterminado: y adaptador predeterminado: grupo de postgresql: 5 tiempo de espera: 5000 desarrollo: <<: *default database: upload_carrier_dev username: 'YOUR_USER' password: 'YOUR_PASSWORD' host: localhost
Cree la base de datos de Postgres correspondiente, y luego genere y aplique la migración:
rieles g migración add_attachments_to_posts archivos adjuntos: json rails db: migrate
Si prefiere seguir con SQLite, siga las instrucciones enumeradas en la documentación de Carrierwave..
Ahora monte los cargadores (¡note la forma plural!):
mount_uploaders: archivos adjuntos, ImageUploader
Estoy usando el mismo cargador para los archivos adjuntos, pero por supuesto puede generar uno nuevo con una configuración diferente.
Agregue el campo de múltiples archivos a su formulario:
<%= f.label :attachments %> <%= f.file_field :attachments, multiple: true %>
Siempre y cuando el archivos adjuntos
El campo contendrá una matriz, se debe permitir de la siguiente manera:
params.require (: post) .permit (: title,: body,: image,: remove_image,: image_cache,: remote_image_url, archivos adjuntos: [])
Por último, puedes recorrer los archivos adjuntos de la publicación y mostrarlos como de costumbre:
<% if @post.attachments? %>
Tenga en cuenta que cada archivo adjunto tendrá una miniatura como se configura en nuestro ImageUploader
. Bonito!
Mantener el almacenamiento de archivos no siempre es conveniente y / o posible, ya que, por ejemplo, en Heroku no es posible almacenar archivos personalizados. Por lo tanto, puede preguntar cómo casarse con Carrierwave con el almacenamiento en la nube de Amazon S3. Bueno, esa es una tarea bastante fácil también. Carrierwave depende de la gema fog-aws para implementar esta función:
gema "fog-aws"
Instalarlo:
instalación de paquete
Vamos a crear un inicializador para Carrierwave y configurar el almacenamiento en la nube a nivel mundial:
CarrierWave.configure do | config | config.fog_provider = 'fog / aws' config.fog_credentials = proveedor: 'AWS', aws_access_key_id: ENV ['S3_KEY'], aws_secret_access_key: ENV ['S3_SECRET'], región: ENV ['S3_REGION'], etc. fog_directory = ENV ['S3_BUCKET'] final
Hay otras opciones disponibles, que se pueden encontrar en la documentación..
Estoy utilizando la gema dotenv-rails para establecer las variables de entorno de forma segura, pero puede elegir cualquier otra opción. Sin embargo, asegúrese de que su par de claves S3 no esté disponible públicamente, porque de lo contrario cualquier persona puede cargar cualquier cosa en su depósito!
A continuación, reemplace el almacenamiento: archivo
linea con:
almacenamiento: niebla
Además de S3, Carrierwave admite cargas a Google Storage y Rackspace. Estos servicios son fáciles de configurar también.
Esto es todo por hoy! Hemos cubierto todas las características principales de Carrierwave, y ahora puede comenzar a usarlo en sus proyectos. Tiene algunas opciones adicionales disponibles, así que navegue por la documentación..
Si estás atascado, no dudes en publicar tus preguntas. Además, podría ser útil echar un vistazo a la wiki de Carrierwave, que contiene artículos útiles de "cómo hacer" que responden a muchas preguntas comunes..
Así que te agradezco por estar conmigo, y feliz codificación!