Deixe suas Rake Tasks mais elegantes com as TTY gems!

Há tempos crio rake takes personalizadas para meus projetos, no entanto, após conhecer o pacote TTY gems percebi que dá pra deixar não só as rake tasks mas tudo relativo ao uso do ruby no terminal muito mais elegante. Simbora aprender mais essa? 🙂

Pois bem, quando entramos no site oficial (http://piotrmurach.github.io/tty/gems/) percebemos que o pacote TTY gems é um conglomerado de 19 gems, todas com especifidades para terminal, e isso, pra quem precisa de soluções baseadas em terminal, é praticamente um paraíso.

Podemos citar algumas gems como a pastel, que permite colorir as saídas no terminal, a tty-cursor, que permite mover o cursor do terminal para qualquer posição da tela, a tty-markdown, que permite mostrar arquivos markdown no terminal, dentre outras.

Claro que não vou conseguir aqui falar de cada uma das gems então escolhi a gem tty-spinner que tem um propósito bem específico que é mostrar um spinner (de vários modelos) enquanto uma determinada ação é feita, algo que pra mim é de grande valia, principalmente quando estou desenvolvendo rake tasks devido a dar um ótimo feedback para quem está usando.

Ok, então vamos colocar a mão na massa!

Bem, vamos começar criando um projeto Rails, depois usaremos o scaffold para gerar um CRUD para dados de um usuário e na sequência criaremos uma rake task para fazermos o cadastro de alguns usuários no sistema. Sendo assim, rodamos os comandos:

rails new meu_projeto
rails g scaffold User name email
rails g task setup user

Ao rodar o último comando será criado o arquivo meu_projeto/lib/tasks/setup.rake onde podemos escrever nossa rake task.

Vamos aproveitar e antes de concluir a rake task criar logo o BD, bem como migrar a tabela pendente, rodando o comando:

rails db:create db:migrate

Prontinho!

Nesse momento, vamos implementar nossa rake task. Digite o conteúdo abaixo no arquivo meu_projeto/lib/tasks/setup.rake.

# meu_projeto/lib/tasks/setup.rake
namespace :setup do
desc "Cadastra 10 usuários no sistema"
task user: :environment do
puts "Cadastrando usuários..."
10.times do |i|
num = rand(9999)
User.create!(
name: "Usuário (#{num})",
email: "
@user.com">user_#{num}@user.com"
)
end
puts "Cadastro efetuado com sucesso!"

end
end

Ao digitar e salvar o conteúdo acima, podemos rodar no prompt…

rails setup:user

Assim teremos cadastrado no banco de dados 10 usuários aleatórios e a saída no prompt fica razoavelmente amigável, conforme abaixo.

/meu_projeto# rails setup:user
Cadastrando usuários…
Cadastro efetuado com sucesso!

No entanto, podemos deixar isso ainda melhor com o gem tty-spinner.

Comece adicionando ela na Gemfile.

# Gemfile
gem 'tty-spinner'

Rode o bundle install para instalá-la.

Agora altere a rake task para:

# meu_projeto/lib/tasks/setup.rake
namespace :setup do
desc "Cadastra 10 usuários no sistema"
task user: :environment do
spinner = TTY::Spinner.new("[:spinner] Cadastrando usuários...")
spinner.auto_spin
    10.times do |i|
sleep(0.5)
num = rand(9999)
User.create!(
name: "Usuário (#{num})",
email: "@user.com">user_#{num}@user.com"
)
end

spinner.success('(Concluído!)')
end
end

Perceba que além das alterações para o uso da gem, adicionei um sleep(0.5)para que a iteração demore um pouco mais, no intuito de você perceber a gem funcionando.

Aproveite e rode mais uma vez a task. A saída final deve ser como abaixo.

/meu_projeto# rails setup:user
[✔] Cadastrando usuários… (Concluído!)

Você deve ter visto agora um spinner funcionando, e na sequência a mesma linha passa a mostrar o palavra (Concluído!).

Acredito que assim como eu você deva ter achado a iteração muito mais amigável para o usuário, mas, ainda dá pra ficar um pouquinho melhor.

Se você perceber, fazer isso em cada rake task que exista no seu projeto vai acabar duplicando muito o código do uso da nova gem, então você pode dar uma refatorada conforme abaixo, fazendo assim com que seja reutilizado o método para mostrar o spinner, veja:

namespace :setup do
desc "Cadastra 10 usuários no sistema"
task user: :environment do
show_spinner("Cadastrando usuários...","(Concluído!)") do
10.times do |i|
sleep(0.5)
num = rand(9999)
User.create!(
name: "Usuário (#{num})",
email: "@user.com">user_#{num}@user.com"
)
end
end
end

def show_spinner(start_msg, end_msg)
spinner = TTY::Spinner.new("[:spinner] #{start_msg}")
spinner.auto_spin
yield
spinner.success("#{end_msg}")
end

end

Prontinho! Agora o código ficou bem DRY e fica muito fácil adicionar novas tasks com uma saída muito amigável no prompt. 🙂

PS. Eu sei que daria pra ter feito isso via seeds.rb e que também podemos testar se um bloco foi passado para o show_spinner, mas julguei mais didático explicar da forma como tudo ficou no post, aprendendo a criar sua própria rake task e sem se preocupar com detalhes de uso de blocos, blz?

Bom, espero que tenham gostado e por enquanto é isso!

Aproveitando, não esquece de nos seguir nas redes sociais e se cadastrar em nossa newsletter semanal, hein! =)

Um super abraço e até a próxima!