Subir imágenes con CarrierWave - moiseserg/rubyWebDev GitHub Wiki

Se actualiza el archivo de gemas, se agrega carrierwave

gem 'carrierwave'
gem 'mini_magick'

Ejecutar rails g para ver el generador que permite subir los archivos

$ rails g
Running via Spring preloader in process 18654
Usage: rails generate GENERATOR [args] [options]

General options:
  -h, [--help]     # Print generator's options and usage
  -p, [--pretend]  # Run but do not make any changes
  -f, [--force]    # Overwrite files that already exist
  -s, [--skip]     # Skip files that already exist
  -q, [--quiet]    # Suppress status output

Please choose a generator below.

Rails:
  assets
  channel
  controller
  generator
  helper
  integration_test
  jbuilder
  job
  mailer
  migration
  model
  resource
  scaffold
  scaffold_controller
  system_test
  task

Coffee:
  coffee:assets

Js:
  js:assets

TestUnit:
  test_unit:generator
  test_unit:plugin

Uploader:
  uploader


El generador que se usará es uploader

Ahora se genera un módulo para subir los archivos:

$ rails g uploader Image
Running via Spring preloader in process 18873
      create  app/uploaders/image_uploader.rb

Podrá visualizar

class ImageUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  # include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
  #   # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process scale: [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  # version :thumb do
  #   process resize_to_fit: [50, 50]
  # end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  # def extension_whitelist
  #   %w(jpg jpeg gif png)
  # end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end
end
  • Descomentar la línea que contiene
include CarrierWave::MiniMagick

para poder utilizar la gema mini_magic

  • storage :file permite usar el sistema de archivos local para almacenar la información. Por otro lado, :fog es otra gema que permite administrar archivos en la nube.
# Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog
  • Para permitir archivos de tipo imagen, se descomenta la siguiente sección:
  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_whitelist
    %w(jpg jpeg gif png)
  end
  • Para especificar una imagen por default si no se ha subido se descomenta la siguiente sección y se cambia para que siempre sea la misma imagen.
# Provide a default URL as a default if there hasn't been a file uploaded:
  def default_url(*args)
  #   # For Rails 3.1+ asset pipeline compatibility:
    ActionController::Base.helpers.asset_path("default.png")
  #
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  end
  • Para generar una versión reducida de la imagen, se puede usar el siguiente fragmento:
# Create different versions of your uploaded files:
  version :thumb do
    process resize_to_fill: [150, 150]
  end

Configurando el Modelo Imagen

Se generará un modelo que corresponderá a un producto, regresando al ejemplo de las pizzas:

rails g scaffold Product name:string description:text price:float  quantity:integer image:string

Después de generar el modelo, se modifica en app/models/product.rb el archivo quedando:

class Product < ApplicationRecord
	mount_uploader :image, ImageUploader
end
  • El método mount_uploader permite hacer la carga de :image (del modelo Producto) ligada con el ImageUploader

Como se había definido una imagen por default para los modelos que no tengan la imagen, se copia alguna imagen con el nombre especificado a la carpeta app/assets/images.

Si se sube una imagen:

c00

Cuando se muestre se verá la cadena asociada al campo de imagen:

c00

Para poder visualizar la imagen (en este caso la imagen que se estableció por default

c00

Se requiere escribir la siguiente línea: <%= image_tag @product.image.thumb.url %> en el archivo app/views/products/show.html.erb o en donde se desee mostrar la imagen almacenada.

<p>
  <strong>Image:</strong>
  <%= @product.image %>
  <%= image_tag @product.image.thumb.url %>
</p>

note que realmente se debe eliminar <%= @product.image %> ya que en general sólo se requiere la imagen no su URL.

En el archivo app/views/product/index.html.erb, la línea <% @products.each do |product| %> hace un ciclo sobre todos los elementos del modelo Producto donde se puede accesder a cada instancia usando la variable product, por lo que para mostrar la imagen se coloca la línea <td><%= image_tag product.image.url %></td> si se desea la imagen original, o de otra forma por ejemplo <td><%= image_tag product.image.thumb.url %></td> si se desea usar la miniatura creada.

 <tbody>
    <% @products.each do |product| %>
      <tr>
        <td><%= product.name %></td>
        <td><%= product.description %></td>
        <td><%= product.price %></td>
        <td><%= product.quantity %></td>
        <td><%= image_tag product.image.url %></td>
        <td><%= link_to 'Show', product %></td>
        <td><%= link_to 'Edit', edit_product_path(product) %></td>
        <td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>

Subiendo imágenes usando file form

Para agregar el componente HTML que permite seleccionar una imagen para ser subida al servidor:

c00

En el elemento que permite definir la imagen (definida como string en el scaffold):

<div class="field">
    <%= form.label :image %>
    <%= form.text_field :image, id: :product_image %>
  </div>

Cambiarlo a un formulario para subir archivos:

 <div class="field">
    <%= form.label :image %>
    <%= form.file_field :image, id: :product_image %>
  </div>

Usando el uploader

  • Subiendo la imagen usando el file chooser

c00

  • Después de ingresar la información, se muestra (show) el registro ingresado

c00

c00

Un video muy util Curso de Ruby on Rails, Subir imagenes

⚠️ **GitHub.com Fallback** ⚠️