Uma mix task é um script Elixir executado através do mix e normalmente utilizado para tarefas corretivas. Neste artigo, iremos escrever uma task para popular uma coluna recém criada em uma tabela no banco de dados.
Infelizmente, é comum encontrarmos aplicações com este tipo de funcionalidade como parte de uma migration. Entretanto, tal abordagem é uma anti-pattern e deve ser evitada. Migrations devem ser utilizadas única e exclusivamente para mudanças na estrutura do banco de dados, e não para a manipulação de dados.
Migrations devem ser utilizadas única e exclusivamente para mudanças na estrutura do banco de dados, e não para a manipulação de dados.
Utilizaremos como exemplo uma aplicação simples de CRUD de guitarras 🎸. O código fonte da aplicação de exemplo deste post está disponível na url a seguir:
https://github.com/idopterlabs/guitar_store/tree/mix-task
Este post é continuação do post deploy de aplicações Phoenix no Heroku. Os passos a seguir funcionam apenas com a estratégia de builpacks — eles não irão funcionar para aplicações que utilizem releases.
No mundo dos instrumentos musicais, existe uma categoria chamada de custom shop. Modelos custom shop são unidades especiais de um instrumento, feitas com especificações únicas, materiais de melhor qualidade e produzidas em quantidade limitada. Por estes motivos, seus preços tendem a ser mais altos do que modelos feitos em maior escala 💸.
Nossa aplicação GuitarStore precisa indicar quando um modelo de guitarra é custom shop. Para isto, iremos adicionar uma coluna à tabela guitars chamada is_custom_shop. O código a seguir é a migration que cria esta nova coluna:
Alguns detalhes desta migration:
Após a execução da migration, novas guitarras adicionadas ao sistema poderão ser marcadas como custom shop através de um checkbox no formulário, ilustrado a seguir:
O checkbox ajuda no cadastro de novas guitarras. Porém, o sistema encontra-se em produção e possui um número de guitarras já cadastradas. Este é um cenário bastante comum no ciclo de desenvolvimento de software. Ao desenvolvermos novas funcionalidades, mudanças no código e na estrutura do banco de dados devem sempre levar em conta os dados já existentes.
Ao desenvolvermos novas funcionalidades, mudanças no código e na estrutura do banco de dados devem sempre levar em conta os dados já existentes.
Todas as guitarras existentes no sistema terão, por padrão, o valor false para o novo campo is_custom_shop. Baseado na regra de negócio que determina se uma guitarra é custom shop, precisamos analisar as guitarras existentes no banco e atualizar a nova coluna.
Iremos classificar uma guitarra como custom shop caso ela seja de uma determinada marca, modelo e ano de fabricação. Para fins ilustrativos, estes dados estão hardcoded no módulo GuitarStore.Utils a seguir:
Um dos benefícios de mantermos o código de manipulação de dados em tasks, e separado do módulo de migrations, é o fato de podermos facilmente testá-lo! Antes do código da task, vamos olhar o código de teste:
As seguintes ações acontecem neste código de teste:
Agora, finalmente, o código da task:
Algumas observações sobre o código da task:
Para rodar a task localmente, executamos o comando a seguir:
mix populate_is_custom_shop
Para rodar a task no Heroku, passamos este comando como argumento para o comando heroku run, como no código a seguir:
heroku run "POOL_SIZE=2 mix populate_is_custom_shop"
Pronto! Concluímos nossa mix task, testada, e que popula uma coluna de banco de dados seguindo uma regra de negócio 💥
Neste artigo, vimos como escrever, testar e executar uma mix task que atualiza uma tabela no banco de dados. Aprendemos que migrations devem ser utilizadas única e exclusivamente para mudanças na estrutura do banco de dados, e não para a manipulação de dados.
Agora você está pronto para escrever mix tasks e executá-las localmente e também no Heroku!
E aí, o que achou ? Caso tenha alguma consideração ou dica, deixe seu comentário! :)
A Idopter Labs é uma empresa de consultoria em desenvolvimento de software com o objetivo de transformar idéias em negócios digitais rentáveis. Prezamos por transparência, objetividade e agilidade. Estamos no mercado desde 2016 e, desde então, ajudamos diversos clientes em suas iniciativas nas mais diferentes indústrias. Adotamos Elixir em nossa stack por sua performance, clareza e pela excelente comunidade que existe ao seu redor.