Vídeo: Aprenda Active Storage - parte 2
Há 3 dias, publiquei o primeiro vídeo desta série sobre Active Storage, o grande destaque do Rails 5.2; recomendo que você o veja antes de assistir este.
Nesse segundo vídeo, vou mostrar como configurar o Active Storage para:
- Fazer upload de arquivos para o AWS S3 (serviço de armazenamento de arquivos da Amazon);
- Usar o direct upload (envio de arquivos do navegador diretamente para o S3, sem passar pelo seu servidor);
- Fazer upload de vários arquivos de uma só vez.
Arquivos alterados no vídeo:
config/storage.yml
yaml# ... amazon: service: S3 access_key_id: xxxxxxxxxxxxxxxxxxxx secret_access_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx region: xxxxxxxxxxxxxx bucket: xxxxxxx # ...
config/environments/development.rb
ruby# ... config.active_storage.service = :amazon # ...
app/assets/javascripts/application.js
javascript// ... //= require activestorage // ...
app/models/post.rb
rubyclass Post < ApplicationRecord has_many_attached :images end
app/controllers/posts_controller.rb
rubyclass PostsController < ApplicationController # ... def post_params params.require(:post).permit(:title, :body, images: []) end end
app/views/posts/_form.html.erb
erb<!-- ... --> <div class="field"> <%= form.label :images %> <%= form.file_field :images, direct_upload: true, multiple: true %> </div> <!-- ... -->
app/views/posts/show.html.erb
erb<!-- ... --> <% @post.images.each do |image| %> <%= image_tag image, style: 'width: 25%' %> <% end %> <!-- ... -->
app/assets/javascripts/direct_uploads.js
javascriptaddEventListener("direct-upload:initialize", event => { const { target, detail } = event const { id, file } = detail target.insertAdjacentHTML("beforebegin", ` <div id="direct-upload-${id}" class="direct-upload direct-upload--pending"> <div id="direct-upload-progress-${id}" class="direct-upload__progress" style="width: 0%"></div> <span class="direct-upload__filename">${file.name}</span> </div> `) }) addEventListener("direct-upload:start", event => { const { id } = event.detail const element = document.getElementById(`direct-upload-${id}`) element.classList.remove("direct-upload--pending") }) addEventListener("direct-upload:progress", event => { const { id, progress } = event.detail const progressElement = document.getElementById(`direct-upload-progress-${id}`) progressElement.style.width = `${progress}%` }) addEventListener("direct-upload:error", event => { event.preventDefault() const { id, error } = event.detail const element = document.getElementById(`direct-upload-${id}`) element.classList.add("direct-upload--error") element.setAttribute("title", error) }) addEventListener("direct-upload:end", event => { const { id } = event.detail const element = document.getElementById(`direct-upload-${id}`) element.classList.add("direct-upload--complete") })
app/assets/stylesheets/direct_uploads.css
css.direct-upload { display: inline-block; position: relative; padding: 2px 4px; margin: 0 3px 3px 0; border: 1px solid rgba(0, 0, 0, 0.3); border-radius: 3px; font-size: 11px; line-height: 13px; } .direct-upload--pending { opacity: 0.6; } .direct-upload__progress { position: absolute; top: 0; left: 0; bottom: 0; opacity: 0.2; background: #0076ff; transition: width 120ms ease-out, opacity 60ms 60ms ease-in; transform: translate3d(0, 0, 0); } .direct-upload--complete .direct-upload__progress { opacity: 0.4; } .direct-upload--error { border-color: red; } input[type=file][data-direct-upload-url][disabled] { display: none; }
Qualquer dúvida, mande nos comentários!