Vídeo: Aprenda Active Storage - parte 2
Aprenda a fazer upload de arquivos para o AWS S3, usar direct upload sem passar pelo seu servidor e também a enviar múltiplos arquivos de uma vez
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
ruby
class Post < ApplicationRecord
has_many_attached :images
end
app/controllers/posts_controller.rb
ruby
class 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
javascript
addEventListener("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!