O que é uma variante
Uma foto de perfil costuma aparecer em vários formatos: uma miniatura numa lista, uma prévia média num card, um recorte grande no próprio perfil. A saída ingênua é enviar três arquivos e cuidar de três registros. A resposta do ActiveStorage é a variant (variante): um arquivo enviado e quantos formatos derivados você pedir, calculados sob demanda em vez de guardados de antemão.
Um blob, várias variantes
course.cover.variant(resize_to_limit: [400, 300])
course.cover.variant(resize_to_limit: [80, 80])
As duas linhas partem do mesmo arquivo enviado, o ActiveStorage::Blob, e descrevem uma transformação, e não um novo upload. Nada é processado quando você escreve essa linha. Uma variante é uma receita, avaliada só quando preciso. O redimensionamento acontece na primeira vez que alguém pede a URL e o arquivo ainda não existe naquele tamanho. Peça a mesma receita depois e o ActiveStorage encontra o arquivo já processado, sem refazer o trabalho.
Por que esta aplicação fixa um processador
Uma receita precisa de algo que leia e redimensione imagens, e o Rails não traz isso. Ele delega à biblioteca de processamento de imagem que estiver configurada. O config/environments/development.rb e o config/environments/production.rb desta aplicação definem:
config.active_storage.variant_processor = :vips
:vips quer dizer libvips, usada pela gem ruby-vips, e os dois ambientes escolhem essa opção. Não é uma comodidade só de desenvolvimento. A outra opção comum, :mini_magick (que embrulha o ImageMagick), ainda é aceita pelo Rails, mas esta aplicação não a usa em lugar nenhum. O vips é o único processador configurado, em todo ambiente que configura algum.
Quanto custa o "sob demanda"
A primeira requisição de uma variante nova paga o processamento da imagem na hora. Ela espera o vips redimensionar o arquivo de origem antes de a resposta sair. As requisições seguintes para a mesma receita pulam o redimensionamento. Elas ainda passam por um controller do Rails, porque esta aplicação serve arquivos em modo proxy (aula 5). O ActiveStorage::Representations::ProxyController encontra a variante processada e devolve o arquivo guardado em streaming. A troca é proposital: uma requisição lenta na primeira vez que um formato é pedido. Em troca, você não precisa prever todos os tamanhos de antemão, e nada precisa ser reprocessado quando o design muda e só algumas páginas pedem um recorte novo.
Pontos-chave
- Uma variante é uma receita de transformação ligada a um blob que já existe, e não um novo upload.
course.cover.variant(resize_to_limit: [400, 300])descreve um formato; não cria nenhum. - As variantes são calculadas só quando pedidas. O redimensionamento acontece na primeira requisição daquela receita, e as seguintes reaproveitam o resultado.
- O
config/environments/development.rbe oproduction.rbdesta aplicação fixamconfig.active_storage.variant_processor = :vips. Alibvips, pela gemruby-vips, é o único processador configurado em toda a aplicação. - A primeira requisição de um formato novo é mais lenta porque paga o redimensionamento. As seguintes pulam essa etapa, mas ainda passam por um controller do Rails que encontra o arquivo processado e o devolve em streaming.
Continue com a aula 2
Anexando uma imagem, ou várias
A diferença entre has_one_attached e has_many_attached, e por que atribuir com = substitui enquanto .attach acrescenta.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.