Criando uma GEM e Clonando o Google Translate (parte 1 de 2)

img-gem-translate-final
O que vamos aprender?

Criar uma GEM pode ser uma maneira muito eficiente de você deixar o seu projeto organizado, fácil de ser reutilizado em projetos futuros e possivelmente ajudar a comunidade do Rails divulgando o código da sua Gem (A gente agradece 🙂 ).

Nesse tutorial eu vou ensinar como criar uma Gem com uso prático e também vou mostrar como você pode utilizá-la dentro de um projeto Rails.

Esse Post é a parte 1 de um tutorial de 2 partes, primeiro nós vamos aprender a criar uma Gem para traduzir frases exatamente como o Google Translate faz e depois no tutorial 2 nós vamos criar um site similar ao Google Translate e usar a nossa Gem para traduzir as frases enviadas pelos usuários.
Prepare-se para criar um projeto bem interessante que pode agregar bastante na sua maneira de entender o Ruby On Rails!

Todo o código da Gem criada está no GitHub, baixe o código se desejar clicando aqui! (Aproveita e me segue lá 🙂 )

Ingredientes (Parte 1)
  • Ruby (2.3.1)
  • Api da Yandex
  • Rest Client (gem)
  • Json (gem)
  • Rspec (gem)
Objetivos do Tutorial (Parte 1)
  • Criar uma Gem
  • Criar os Testes para a nossa Gem (Todos os métodos) usando Rspec
  • Criar um método para identificar o idioma de uma frase
  • Criar um método para saber quais os idiomas a Api da Yandex conhece
  • Criar um método para traduzir uma frase para outro idioma que a Api da Yandex conheça
Mãos à Obra
Gerando e configurando nossa Gem
  1. Primeiro você precisa ter o Ruby instalado, caso você não tenha aprenda como instalar usando o RVM clicando aqui.
  2. Agora instale o Bundle rodando no console:
    1
    
    gem install bundle
  3. Vamos gerar a nossa Gem rodando no console:
    1
    
    bundle gem translate_yandex
  4. Ótimo nossa Gem foi gerada, observe na imagem abaixo os diretórios que foram gerados:
    rails gem
  5. Fica como um exercício pra você, pesquisar sobre Versionamento de Gems. 🙂
  6. Agora nós vamos configurar a nossa Gem no arquivo “translate_yandex.gemspec”, essa configuração vai ficar visível para as pessoas que encontrarem a nossa Gem no  https://rubygems.org/ quando fizermos o upload.
      • Primeiro você precisa configurar essas linhas:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        
        #Nome da Gem
        spec.name = "translate_yandex"
        #Nome do Autor da Gem
        spec.authors = ["Leonardo Scorza"]
        #Email do autor da Gem
        spec.email = ["contato@gmail.com"]
        #Essa é a descrição curta da Gem
        spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.}
        #Essa é a descrição Longa da Gem
        spec.description = %q{TODO: Write a longer description or delete this line.}
        #Coloque o link para o repositório do Github ou para a Homepage do site onde você vai deixar a documentação da Gem
        spec.homepage = "TODO: Put your gem's website or public repo URL here.

     

  7. Agora verifique se você encontra essa linha no seu arquivo “translate_yandex.gemspec”:
  8. 1
    
    spec.add_development_dependency "rspec", "~> 3.0"

    Caso não exista, insira essa linha e rode:

    1
    
    bundle install

    Nós vamos precisar do Rspec para os testes

  9. Para finalizar insira também essa linha:
    1
    
    spec.add_development_dependency "rest-client"

    e rode:

    1
    
    bundle install

    Você precisa substituir todos os “TODO” das configurações, se não você não vai conseguir rodar o Rspec ou instalar a Gem.

Pegando nossa Api Key

Como eu disse no inicio desse post, para realizar as traduções nós vamos usar a Api da Yandex. Para podermos usar a Api deles nós precisamos de uma chave para receber a autorização durante as chamadas da Api.

  1. Primeiro acesse esse  link!
    captura-de-tela-de-2016-09-18-22-45-24
  2. Depois de preencher seus dados você deve entrar nessa tela, basta checar o “User Agreement” e prosseguir:
    captura-de-tela-de-2016-09-18-22-48-54
  3. Certo, agora você já deve estar na página que mostra sua chave, basta copiá-la para um lugar seguro. Logo iremos usá-la.
    captura-de-tela-de-2016-09-18-22-49-10

Pronto, agora com nossa chave nós podemos finalmente criar os testes.

Criando os Testes para a nossa Gem (TDD)

Seguindo a prática de TDD nós vamos começar criando os testes antes do código da Gem  propriamente dita, se você quiser saber mais sobre essa prática clique aqui. (Se você quiser que eu explique TDD e o Rspec nesse blog comente aí em baixo 🙂 ou me adicione no Facebook pra gente bater um papo clicando aqui)

Na nossa Gem nós queremos criar três métodos principais:

  1. Um método capaz de traduzir uma frase do idioma X para o idioma Y.
  2. Um método que retorne todos os idiomas que a API da Yandex conhece.
  3. Um método capaz de dizer em qual idioma uma frase foi escrita.

Com nossos objetivos  em mente, vamos começar.

Inserindo a nossa Chave da Api

Nós precisamos passar uma chave válida da API para o Rspec poder usá-la na hora que formos inicializar nossa classe dentro dele.
Para fazer isso vá até o arquivo “/spec/spec_helper.rb” e cole essa linha no final do arquivo com a sua chave da API:

1
TEST_API_KEY = "SUA_CHAVE_DE_TESTE_AQUI"

O recomendado é que você crie uma nova chave no site da Yandex apenas para teste e use ela nesse arquivo. (Se você fizer o upload da sua Gem sua chave será visível para outras pessoas, então se usar sua chave normal outras pessoas vão ter acesso a ela)

Primeiro Teste
  1. Copie o código a baixo e cole no seu arquivo “spec/translate_yandex_spec.rb”:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    require "spec_helper"
    describe "GET api/v1.5/tr.json/translate (Translate)" do
      # Teste 1 (Translate)
      it "Api response == 200" do
        textPt = "Nós estamos testando o tradutor"
        yandexApi = TranslateYandex::Yandex.new TEST_API_KEY
        response = yandexApi.translate textPt, "en"
        expect(response["code"]).to eq(200)
      end
     
      it "translated text match" do
        textPt = "Nós estamos testando o tradutor"
        textEn = "We are testing the translator"
        yandexApi = TranslateYandex::Yandex.new TEST_API_KEY
        response = yandexApi.translate textPt, "en"
     
        expect(response["text"].first).to eq(textEn)
      end
    end

    Nós criamos dois testes, o primeiro “Api response == 200” para verificar se a Api iria retornar o status de sucesso “200” e o segundo “translatated text match” para verificar se o texto foi traduzido corretamente de português para inglês. Este teste serve para verificar  se estamos chamando a tradução corretamente, não estamos completamente seguros porque dependemos que a Api nunca falhe, mas quanto a isso não temos o que fazer.

  2. Agora rode no console:
    1
    
    bundle exec rspec
  3. Pronto, seu retorno deve ter sido um erro similar a este:
    captura-de-tela-de-2016-09-18-22-14-18Falhou porque nós só temos os testes, não temos ainda o código da Gem :).
Segundo Teste
  1. Copie para o arquivo “spec/translate_yandex_spec.rb” dentro do bloco “describe TranslateYandex do” este código:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    # Teste 2 (supported list of languages)
    describe "GET api/v1.5/tr.json/getLangs (Supported List)" do
      it "Api response not equal nil or empty '' " do
        yandexApi = TranslateYandex::Yandex.new TEST_API_KEY
        response = yandexApi.list
        expect(response).not_to eq(nil)
        expect(response).not_to eq("")
      end
    end

    Nesse teste nós apenas verificamos se a Api não está devolvendo a lista de linguagens que ela suporta vazia ou o response está vindo ‘nil’. Não comparei com a lista de idiomas porque quando ela sofrer alterações vai quebrar nossos testes. Mas aceito contra argumentos sobre isso 🙂

  2. Rode no Console:
    1
    
    bundle exec rspec
  3. Você receberá novamente um erro, agora do teste 1 e do teste 2.

Quando criarmos o código os erros desaparecerão :).

Terceiro Teste
  1. Copie para o arquivo “spec/translate_yandex_spec.rb” dentro do bloco “describe TranslateYandex do” este código:
  2. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    # Teste 3 (Language Detect)
    describe "GET api/v1.5/tr.json/detect (Detect)" do
      it "Api response == 200" do
        textPt = "Nós estamos testando o tradutor"
        yandexApi = TranslateYandex::Yandex.new TEST_API_KEY
        response = yandexApi.detect textPt
        expect(response["code"]).to eq(200)
      end
     
      it "detect language match with right language" do
        textPt = "Nós estamos testando o tradutor"
        yandexApi = TranslateYandex::Yandex.new TEST_API_KEY
        response = yandexApi.detect textPt
        expect(response["lang"]).to eq("pt")
      end
    end

    Dessa vez nós testamos primeiro “Api response == 200” ou seja se a Api estava retornando o código de sucesso e “detect language match with right language” que verifica se realmente a Api está nos dizendo que o idioma da frase é Português.

  3. Agora rode no console:
    1
    
    bundle exec rspec
  4. Novamente você vai receber uma mensagem de erro, agora para todos os testes que fizemos.

Pronto, nossos testes foram criados, se você quiser saber mais sobre o Rspec dá uma olhada nesse link!

Criando o Core da nossa Gem

Pronto, finalmente vamos criar o Core da nossa Gem. Apenas relembrando nosso objetivo é criar os seguintes métodos:

  1. Um método capaz de traduzir uma frase do idioma X para o idioma Y.
  2. Um método que retorne todos os idiomas que a API da Yandex conhece.
  3. Um método capaz de dizer em qual idioma uma frase foi escrita.

Vá até o arquivo “lib/translate_yandex.rb” e cole o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
require "translate_yandex/version"
# Dependencia da gem que faz a chamada REST
require "rest-client"
# Dependencia para parsear o JSON
require "json"
 
module TranslateYandex
  class Yandex
 
    # Aqui nós recebemos a chave da Api quando o usuário inicializa a nossa classe
    def initialize(api_key)
      @api_key = api_key
    end
 
    # Nosso método de tradução
    def translate text, language
      result =  RestClient.get 'https://translate.yandex.net/api/v1.5/tr.json/translate', {params: {key: @api_key, text: text, format: 'plain', lang: language}}
      JSON.parse(result.body)
    end
 
    # Nosso método para receber a lista de idiomas que a API conhece
    def list
      result =  RestClient.get 'https://translate.yandex.net/api/v1.5/tr.json/getLangs', {params: {key: @api_key}}
      JSON.parse(result.body)
    end
 
    # Nosso método que identifica o idioma de uma frase
    def detect text
      result =  RestClient.get 'https://translate.yandex.net/api/v1.5/tr.json/detect', {params: {key: @api_key, text: text}}
      JSON.parse(result.body)
    end
  end
end

Eu fiz alguns comentários no código acima para você entender o que foi feito.
Basicamente estamos com a nossa Gem pronta, agora vamos rodar nossos testes e ver se eles funcionam.

1
bundle exec rspec

Se tudo deu certo você deve estar vendo algo semelhante a isso:
captura-de-tela-de-2016-09-18-23-56-16\o/ Uauuu você acaba de criar a sua primeira Gem e eu acredito que muitas outras virão. Então imagine outras funções que possam ser bem atendidas por uma Gem e usando os conhecimentos que você adquiriu aqui, crie ela.
Se precisar de alguma ajuda comenta aí em baixo ou fale comigo clicando aqui!

Instalando nossa Gem

Para podermos usar a Gem dentro de um projeto Rails por exemplo nós precisamos instalar ela. Para instalar rode:

1
gem build translate_yandex.gemspec

Agora rode:

1
gem install translate_yandex-0.1.0.gem

\o/ Pronto, sua Gem já está instalada e já pode ser usada dentro de um projeto Rails.

Usando nossa Gem via Console

Vamos testar nossa Gem usando ela via console:

  1. No seu console rode:
    1
    
    irb
  2. Você deve estar vendo uma tela como esta:
    captura-de-tela-de-2016-09-19-00-44-16
  3. Agora rode o seguinte comando:
    1
    
    require 'translate_yandex'
  4. Vamos criar nosso objeto (substitua com sua api key):
    1
    
    yandex = TranslateYandex::Yandex.new 'SUA_API_KEY'
  5. Agora vamos pedir para a Gem traduzir a frase “Parabéns por fazer esse tutorial” para Russo:
    1
    
    yandex.translate "Parabéns por fazer esse tutorial", "ru"

captura-de-tela-de-2016-09-19-00-50-16Sucesso, nossa Gem funciona perfeitamente. Se você quiser, você pode testar os outros métodos como uma maneira de fixação :).

 

Publicando nossa Gem

Podemos subir a nossa Gem para o Ruby Gems para que outras pessoas possam usar a nossa Gem e se beneficiar do nosso trabalho assim como nós nos beneficiamos do trabalho de tantos outros que fizeram Gems como “paperclip”, “capistrano”, “rspec” e etc. (Seja legal com o mundo e compartilhe :)).

Publicar a Gem vai ser uma missão para você fazer sozinho, para que você possa fixar mais o conteúdo.
Mas é claro, aqui está uma referência para você saber como fazer!

Se você precisar de ajuda fale comigo :).

Parte 2 (“Clonando” o Google Translate)

Na segunda parte desse tutorial nós vamos aprender como criar um site semelhante ao Google Translate e como usar a Gem que criamos dentro do projeto para identificar o idioma da frase digitada, mostrar a lista de idiomas que podemos traduzir e efetivamente traduzir as frases que o usuário entrar na interface gráfica que criaremos.

Quando o tutorial sai? Vai sair nos próximos dias, talvez um ou dois tutoriais venham antes dele. Mas em breve ele vai estar por aqui. Então se inscreva na nossa newsletter e curta nossa página no Facebook (clicando aqui) para receber notificações quando esse e outros tutoriais saírem.

Você está gostando do que eu estou produzindo? Comenta aí em baixo para eu saber. E se puder compartilha esse conteúdo, isso ajuda bastante a incentivar novos conteúdos. 🙂

Obrigado,
Até o próximo tutorial,
Leonardo Scorza.

Deixe seu Feedback!

Comentários