Fazendo upload de imagem e múltiplos anexos usando CarrierWave

carrierwave21
Introdução 🙂

É muito comum você precisar fazer o upload de fotos ou múltiplos anexos em suas aplicações Web e o Rails fornece Gems que facilitam muito esse processo.

O que vamos aprender?

Nesse tutorial nós vamos usar o CarrierWave + Bootstrap + Simple Form para criar uma página que servirá para fazer o Upload de uma foto e de múltiplos anexos, vamos aprender também como limitar o upload de arquivos baseado na extensão.

INGREDIENTES
Objetivos

Criar um Form para fazer o upload de uma foto e de múltiplos anexos simulando uma página de perfil de um usuário (necessidade comum nos Web Apps).

Passo a Passo
  1. Criar a estrutura do nosso Projeto
  2. Criar os Uploaders e personalizá-los pra limitar o upload por tipo de extensão e separar por vários tamanhos de imagem.
  3. Personalizar nossos Views para subir os arquivos e depois mostrá-los
Mãos à Obra \o/
Parte 1 – Criando a estrutura do Projeto

Primeiro vamos criar nosso projeto Rails, instalar as dependências, incluir as Gems e criar o scaffold User para guardar os dados do usuário.

  1. Para começar, rode no seu console o comando para gerar o projeto:
    1
    
    rails new form_uploader --database=postgresql
  2. Nós precisamos instalar o imagemagick no sistema:
    • Em sistemas linux que usem o apt-get, rode:
      1
      
      sudo apt-get install imagemagick
    • No Mac:
      1
      
      sudo brew install imagemagick
  3.  No seu Gemfile, adicione as seguintes Gems:
    1
    2
    3
    4
    
    gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'
    gem 'bootstrap', '~> 4.0.0.alpha5'
    gem 'simple_form'
    gem 'mini_magick', '~> 4.3'
  4. Vamos rodar o Bundle para instalar as Gems:
    1
    
    bundle
  5. Nós estamos usando nesse tutorial o PostgreSQL como banco de dados para poder usar o tipo “json” do banco de dados que será útil para conectar os múltiplos anexos facilmente, então configure as credenciais do seu banco de dados no arquivo ‘config/database.yml’.
  6. Vamos instalar o Bootstrap para dar uma aparência melhor à nossa aplicação:
    • Substitua o conteúdo do arquivo ‘app/assets/stylesheets/application.css’ pelo seguinte código:
      1
      
      @import "bootstrap";

      Seu arquivo deve ficar dessa maneira:
      captura-de-tela-de-2016-11-26-20-35-53

    • Renomeie o arquivo app/assets/stylesheets/application.css’ para app/assets/stylesheets/application.scss’
    • Adicione no arquivo ‘app/assets/javascripts/application.js’ o seguinte  código após a linha //= require jquery:
      1
      
      //= require bootstrap-sprockets

      Seu código deve ficar como a baixo:
      carrierwave

  7. Vamos instalar agora o Simple Form passando o parâmetro do bootstrap para que nosso form já seja gerado responsivo:
    1
    
    rails generate simple_form:install --bootstrap
  8. Agora vamos criar o Scaffold, rode no console:
    1
    
    rails g scaffold User first_name:string last_name:string email:string about:text
  9. Crie o banco de dados e rode as migrations, no console rode:
    1
    2
    
    rake db:create
    rake db:migrate
  10. Acesse seu projeto no browser http://localhost:3000/users e veja seu scaffold criado.

Pronto \o/, nosso projeto foi criado, agora vamos criar os Uploaders.

Parte 2 – Criar os Uploaders

Agora nós vamos criar dois perfis de Uploaders, incluí-los no User e customizá-los.

  1. Vamos criar o perfil para nossas imagens, rode:
    1
    
    rails generate uploader Avatar
  2. Agora inclua o avatar no nosso model User:
    1
    
    rails g migration add_avatar_to_users avatar:string
  3. Agora vamos configurar o Uploader Avatar para impedir que arquivos que não sejam jpg, gif ou png sejam aceitos pelo servidor, no arquivo ‘app/uploaders/avatar_upload.rb’ substitua o conteúdo por esse código:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    class AvatarUploader < CarrierWave::Uploader::Base
      # Adiciona o MiniMagick para permitir o redimensionamento das imagens
      include CarrierWave::MiniMagick
     
      storage :file
     
      # Local onde será guardado as imagens
      def store_dir
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
      end
     
      ## Tamanhos que o CarrierWave vai salvar as imagens
     
      # Thumb
      version :thumb do
         process resize_to_fit: [50, 50]
      end
     
      # Medium
      version :medium do
         process resize_to_fit: [150, 150]
      end
     
      # Big
      version :big do
         process resize_to_fit: [300, 300]
      end
     
      # Tipos de extensão aceitas
      def extension_whitelist
         %w(jpg jpeg gif png)
      end
    end
  4. Vamos criar o perfil para nossos anexos:
    1
    
    rails generate uploader Document
  5. Inclua os documents (anexos) no nosso model User, para isto rode:
    1
    
    rails g migration add_documents_to_users documents:json
  6. Agora vamos configurar o Uploader Documents, no arquivo ‘app/uploaders/document_upload.rb’ substitua o conteúdo por esse código:
    1
    2
    3
    4
    5
    6
    7
    
    class DocumentUploader < CarrierWave::Uploader::Base
      storage :file
     
      def store_dir
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
      end
    end
  7. Vamos adicionar ao app/model/user.rb à conexão com nossos uploaders, no arquivo inclua:
    1
    2
    
    mount_uploader :avatar, AvatarUploader
    mount_uploaders :documents, DocumentUploader
  8. Vamos rodar as migrations:
    1
    
    rake db:migrate
  9. Inclua no arquivo ‘config/envoriment.rb’ o seguinte código:
    1
    
    require 'carrierwave/orm/activerecord'

    Seu código deve ficar assim:
    captura-de-tela-de-2016-11-26-19-32-25

Parte 3 – Personalizar as Views para subir a foto e os múltiplos anexos

Finalmente vamos editar nossas Views para poder fazer o Upload da foto e dos múltiplos anexos ao nosso projeto.

  1. Vamos adicionar ao form que foi gerado no scaffold os campos de photo e documentos, no file ‘app/views/users/_form.html.erb’ substitua o código por:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    <%= simple_form_for(@user) do |f| %>
      <%= f.error_notification %>
     
      <div class="form-inputs">
        <%= f.input :first_name %>
        <%= f.input :last_name %>
        <%= f.input :email %>
        <%= f.input :about %>
        <%= f.label 'Photo' %>
        <%= f.file_field :avatar %>
        <br/>
        <%= f.label 'Documentos' %>
        <%= f.file_field :documents, multiple: true %>
      </div>
      <br />
     
      <div class="form-actions">
        <%= f.button :submit %>
      </div>
    <% end %>
  2. Edite seu User Controller (‘app/controllers/user_controller.rb’) para receber seus arquivos, para fazer isto altere seu método users_params para que ele fique da seguinte maneira:
    1
    2
    3
    
    def user_params
          params.require(:user).permit(:first_name, :last_name, :email, :about, :avatar, {documents: []})
    end
  3. Agora vamos incluir na view app/views/user/show.html.erb as tags rails para mostrar o avatar que fizemos o upload e também os documentos. Substitua o conteúdo do arquivo pelo seguinte:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    <p id="notice"><%= notice %></p>
     
    <p>
      <strong>First name:</strong>
      <%= @user.first_name %>
    </p>
     
    <p>
      <strong>Last name:</strong>
      <%= @user.last_name %>
    </p>
     
    <p>
      <strong>Email:</strong>
      <%= @user.email %>
    </p>
     
    <p>
      <strong>About:</strong>
      <%= @user.about %>
    </p>
     
    <hr />
     
    <h4>Avatar vários tamanhos</h4>
    Thumb:
    <%= image_tag(@user.avatar.thumb) if @user.avatar %>
    Medium:
    <%= image_tag(@user.avatar.medium) if @user.avatar %>
    Big:
    <%= image_tag(@user.avatar.big) if @user.avatar %>
    <hr />
     
    <h4>Documentos</h4>
    <% @user.documents.each_with_index do |document, index| %>
      <%= link_to("Anexo #{index + 1} ", document.url, target: '_blank') %>
      <br />
    <% end %>
     
    <hr />
     
     
    <%= link_to 'Edit', edit_user_path(@user) %> |
    <%= link_to 'Back', users_path %>
  4. Agora abra o browser e visite http://localhost/users.
  5. Crie um novo usuário passando um first_name, last_name, email, um avatar (photo) e vários arquivos no campo documents.
  6. Agora você vai ser redirecionado pro método show e vai poder ver as fotos em vários tamanhos e também os links para todos os documentos que você subiu.
  7. \o/ Parabéns nós conseguimos subir nossos arquivos.
CONCLUSÃO

O CarrierWave é uma Gem bem prática e te dá muita flexibilidade na hora de subir seus arquivos, então se você precisa implementar essa função no seu APP, esse pode ser um bom caminho para fazer isto.
Com a solução apresentada já é possível você cobrir grande parte dos casos de uso de upload de fotos e anexos mas caso você precise subir arquivos para uma Api Rails você pode usar a Gem Carrier Base 64 para fazer isso facilmente.
Com essa Gem você pode também subir os arquivos diretamente para o S3 da AWS e ter maior segurança por guardar as imagens na nuvem.

Como de costume o Código completo da aplicação está no Github, caso você queria clonar o código, clique aqui. Aproveita e me segue lá \o/

Se você ficou com dúvidas ou tem sugestões de posts para o Blog comenta aí em baixo ou me adiciona no Facebook clicando aqui.

Muito Obrigado,
Sua presença aqui é uma honra para mim,
Leonardo Scorza 🙂

Deixe seu Feedback!

Comentários