Como criar uma gem?
Published: 2022-12-17 22:38:42

Possivelmente um dia irei fazer uma talk sobre isso pois é algo que sempre gostei muito de fazer, criar uma gem as vezes se faz necessário para lidar com algum serviço especifico que poderá ser usado por exemplo, outros micro serviços. É muito importante pensar se devemos criar um gem ou apenas uma nova lib e em minha opinião devemos considerar reusabilidade, esse serviço será usado em mais de uma aplicação? Se sim, devemos considerar criar uma gem para isso, claro, podemos olhar no rubygems para ver se já não existe uma solução para o problema. Sempre achei a criação de gems uma das melhores formas de se praticar programar em ruby, você pode criar algo util e ainda aplicar conceitos de programação, mas por onde começar?

## Conhecendo o Bundler

Bundler é uma ferramenta para gerenciar dependências de um projeto ruby, rails ou não, ele é resposável por ler um arquivo chamado Gemfile, onde deve ser especificado primeiro, qual será a fonte de onde o bundler irá baixar as dependências do projeto e quais serão, de fato, as dependências que serão usadas no projeto, porém o bundler também nos fornece uma arquitetura ideal para nossas gems e para começar é bem simples vamos criar uma gem para interagir com a api da spacex:

`bundler gem spacex_api`

Após rodar o comando acima, ele começará a perguntar algumas coisas, como por exemplo qual framework de testes gostaríamos de usar, eu gosto do minitest, mas vamos de rspec por ser o mais usado atualmente, então é só escrever `rspec`, em seguida ele pergunta qual serviço de CI vc ira usar, no nosso caso será `none`, nas seguintes respostas fica a sua escolha, pois é apenas se você quer adicionar um código de conduta e um changelog, não serão necessários no momento, então fica a sua escolha, depois desses dois passos podemos escolher um linter, eu sempre opto pelo rubocop, então eu digito `rubocop` e isso conclui a nossa configuração inicial da nossa gem, devemos agora ter um diretório chamado `spacex_api`.

## Estrutura de diretórios
- bin -> Diretório onde ficará os binários de nossa gem.
- lib -> Diretório onde será colocado os arquivos de códigos da gem
- spec -> onde ficará os testes unitários da gem
- sig
- spacex_api.gemspec -> arquivo de configuração da gem, como informações sobre e também podemos por as dependências nesse arquivo
- Rakefile -> Um lugar onde comumente colocamos tasks
- README.md -> Instruções de como instalar e usar nossa gem
- LICENSE.txt -> arquivo de licença
- Gemfile -> Onde sao listadas as gems do nosso projeto e suas versoes
- CODE_OF_CONDUCT.md -> um código de conduta com algumas recomendacoes sobre como contribuir e tratar os membros do projeto
- CHANGELOG.md -> arquivo onde lista versões e suas respectivas mudanças

O código da gem ficará dentro de lib/spacex_api, podemos criar arquivos, como módulos mesmo, para cada contexto, por exemplo, podemos criar o arquivo lib/spacex_api/requester.rb ou algo do tipo, e criar outros módulos que serão responsáveis por get, post, inicialmente, o arquivo lib/spacex_api.rb é nosso arquivo principal e podemos importar o requester nele passando alguns parâmetros como o verbo http, url e ao chamar o requester ele devera saber o que fazer baseado apenas no verbo http, no próximo capitulo pretendo implementar ela por completo mas o restante é basicamente ruby puro e esse é um dos motivos de eu gostar tanto de fazer gems.

Uma vez que você comece a criar gems, ira querer fazer gem para tudo, o que eu acho que não está totalmente errado, mas devemos levar em conta a reusabilidade e o tipo de dado que será tratado, o uso de gems é ideal para por exemplo integrações, como essa da spacex, devemos sempre considerar o desacoplamento e sempre ter interfaces de conexão, por exemplo, devemos sempre ter uma interface entre a nossa gem e a nossa aplicação justamente para caso apareça uma solução melhor não exista obstáculos técnicos para que, ao invés de usarmos nossa gem possamos usar uma nova solução.

No mais, pretendo implementar a gem como uma forma de exemplo no próximo capitulo.