Desde a versão 5.2 do Rails seu principal recurso para lidar com envio de arquivos é o Active Storage. Atualmente ele facilita muito a configuração da aplicação para upload, o que antes só era possível por meio da instalação de gems.
Neste artigo não vamos mostrar como configurar o Active Storage. Para isso você pode consultar a documentação oficial do Rails ou algum dos links listados nas referências. Aqui vamos mostrar como você pode testar o fluxo de envio de imagens em uma aplicação e anexar arquivos nos seeds do seu projeto.
Vamos considerar uma aplicação em que podemos cadastrar filmes com título, diretor e uma imagem de capa. Chamaremos a classe de Movie
e seu atributos title
, director
e cover
. Lembrando que, pela maneira como Active Record funciona, basta incluir cover
dentro da classe Movie
com has_one_attached :cover
:
class Movie < ApplicationRecord
has_one_attached :cover
end
Se você quiser escrever um teste para o formulário de cadastro de um filme, podemos usar o método attach_file
do Capybara para simular o envio da imagem de capa. O teste poderia ficar assim:
feature 'Visitor register movie' do
scenario 'successfully' do
visit root_path
click_on 'Registrar filme'
fill_in 'Título', with: 'Contos de Terramar'
fill_in 'Diretor', with: 'Gorō Miyazaki'
attach_file 'Foto de capa', Rails.root.join('spec', 'support', 'contos_de_terramar.jpg')
click_on 'Enviar'
expect(current_path).to eq movie_path(Movie.last)
expect(page).to have_css('h1', text: 'Contos de Terramar')
expect(page).to have_css('h2', text: 'Gorō Miyazaki')
expect(page).to have_css('img[src*="contos_de_terramar.jpg"]')
end
end
O método attach_file
recebe uma string referente ao label do elemento que ele deve encontrar na página e o caminho do arquivo a partir da raiz do projeto que deve ser anexado. No caso deste exemplo, usamos a label 'Foto de capa' para indicar o elemento e o arquivo é o contos_de_terramar.jpg
, dentro do diretório spec/support/
.
Da mesma maneira que podemos criar expectativas nos testes para avaliar a presença de determinados elementos de textos nas views da aplicação, podemos também procurar por elementos de imagens para sabermos se o arquivo correto é renderizado em tela. Note como na última linha de expectativas do teste acima temos have_css('img[src*="contos_de_terramar.jpg"]')
, que procura por um elemento da tag img
com o arquivo específico como source
. Desde que a view contenha um elemento tipo <img>
que carrega o arquivo indicado, seu teste deve passar.
Bônus
Outro lugar em que é útil saber como anexar arquivos com Active Storage é no seeds
, na criação de objetos para o banco. Seguindo o exemplo da aplicação de catálogo de filmes, poderíamos criar objetos com imagens de capa da seguinte forma:
movie = Movie.create(title: 'Contos de Terramar',
director: 'Gorō Miyazaki')
movie.cover.attach(io: File.open(Rails.root.join('spec', 'support', 'contos_de_terramar.jpg')), filename: 'contos_de_terramar.jpg')
Neste exemplo utilizamos spec/support
para armazenar a imagem, mas o recomendado é escolher um diretório mais adequado para o caso do seu projeto.