Conheça as melhores práticas de como criar uma API RESTful completa e segura com o Phoenix 1.7.
Para criar o CRUD de categorias, vamos utilizar o seguinte comando: mix phx.gen.json Blog Category categories name:string
Este comando irá gerar um novo schema chamado Category, que será usado para armazenar as informações das categorias, e o respectivo controlador, as visões e as rotas para lidar com as operações de CRUD.
Após a execução do comando, podemos verificar as mudanças no nosso projeto e realizar a migração do banco de dados para que o schema Category seja criado. Para isso, podemos executar os seguintes comandos:
mix ecto.migrate
###CRUD de Artigos
Para criar o CRUD de artigos, vamos utilizar o seguinte comando:
mix phx.gen.json Blog Article articles title:string body:text user_id:references:users category_id:references:categories
Este comando irá gerar um novo schema chamado Article, que será usado para armazenar as informações dos artigos, e o respectivo controlador, as visões e as rotas para lidar com as operações de CRUD. Neste caso, também estamos relacionando os artigos com os usuários e as categorias.
Após a execução do comando, podemos verificar as mudanças no nosso projeto e realizar a migração do banco de dados para que o schema Article seja criado. Para isso, podemos executar os seguintes comandos:
mix ecto.migrate
Para criar o CRUD de comentários, vamos utilizar o seguinte comando: mix phx.gen.json Blog Comment comments body:text user_id:references:users category_id:references:categories article_id:references:articles
Este comando irá gerar um novo schema chamado Comment, que será usado para armazenar as informações dos comentários, e o respectivo controlador, as visões e as rotas para lidar com as operações de CRUD. Neste caso, também estamos relacionando os comentários com os usuários, as categorias e os artigos.
Após a execução do comando, podemos verificar as mudanças no nosso projeto e realizar a migração do banco de dados para que o schema Comment seja criado. Para isso, podemos executar os seguintes comandos: mix ecto.migrate
Com a criação dos CRUDs, podemos prosseguir com a configuração das rotas para permitir o acesso aos recursos da API.
Para adicioná-las, basta usar o resources do Phoenix 1.7, que gera automaticamente as rotas necessárias para CRUD (Create, Read, Update, Delete) e mapeia para os métodos correspondentes nos controladores.
No primeiro argumento do resources, informamos o nome da rota, e no segundo, o controlador correspondente. O parâmetro except indica quais rotas devem ser excluídas da geração automática. Neste caso, estamos excluindo as rotas de criação e edição.
As rotas específicas para o sistema de blog incluem a rota de categorias (/categories), a rota de artigos (/articles) e a rota de comentários (/comments).
Para adicioná-las, basta adicionarmos o código abaixo no segundo escopo do arquivo router.ex:
resources “/users”, UserController, except: [:new, :edit]
resources “/categories”, CategoryController, except: [:new, :edit]
resources “/articles”, ArticleController, except: [:new, :edit]
resources “/comments”, CommentController, except: [:new, :edit]
Com essas rotas adicionadas, já podemos criar, ler, atualizar e deletar dados dos schema de Categoria, Artigo e Comentário.
Por exemplo, a rota /categories terá as seguintes rotas geradas automaticamente:
Método HTTP URL Função do controlador Descrição
GET /api/categories index Retorna todas as categorias
GET /api/categories/:id show Retorna a categoria com o id especificado
POST /api/categories create Cria uma nova categoria
PUT /api/categories/:id update Atualiza a categoria com o id especificado
DELETE /api/categories/:id delete Deleta a categoria com o id especificad
Para testar as rotas, é possível usar ferramentas como o Postman ou o cURL, fazendo requisições HTTP para a API em execução. Para iniciar o servidor do Phoenix, basta navegar até a raiz do projeto e executar o comando “mix phx.server”. Assim, o servidor estará pronto para receber as requisições e retornar as respostas correspondentes.
##Testes gerados pelo Phoenix e cobertura de testes
O Phoenix 1.7 possui um sistema de testes integrado que é gerado automaticamente para as nossas aplicações. Quando usamos o comando mix phx.gen.json para gerar o código para o CRUD, o Phoenix cria automaticamente os arquivos de teste necessários para a nossa aplicação.
Os arquivos de teste são criados em uma estrutura de diretórios específica, dentro da pasta test do nosso projeto. O Phoenix gera testes para os schemas, controles e visões, além de testes de integração para cada rota da nossa aplicação.
Para executar os testes gerados pelo Phoenix, basta rodar o comando mix test no terminal, na raiz do projeto. Isso executará todos os testes da aplicação e exibirá o resultado no terminal. Podemos executar testes individuais também, especificando o caminho do arquivo de teste. Por exemplo, para executar apenas os testes para o schema de categoria, podemos executar o comando mix test test/models/category_test.exs.
Além de executar os testes, é importante verificar a cobertura de testes da nossa aplicação. O Phoenix 1.7 fornece uma ferramenta integrada para isso, chamada ExCoveralls. Essa ferramenta gera um relatório de cobertura de testes que pode ser visualizado em formato HTML.
Para instalar a biblioteca ExCoveralls, adicione-a ao arquivo mix.exs como uma dependência de desenvolvimento:
def deps do
[
{:excoveralls, "~> 0.16.0", only: :test}
]
end
Em seguida, execute o comando mix deps.get para instalar a biblioteca.
Para gerar o relatório de cobertura de testes, você precisa executar os testes com a opção --cover ativada. Por exemplo:
mix test --cover
Isso irá gerar um arquivo de cobertura no formato JSON na pasta cover. Para gerar a cobertura em html prcisamos adicionar ainda mais uma configuração dentro do mix.exs:
def project do
[
app: :my_app,
version: "0.1.0",
elixir: "~> 1.14",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps(),
test_coverage: [tool: ExCoveralls],
preferred_cli_env: [
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test
]
]
end
Repare que adicionamos o trecho de código:
test_coverage: [tool: ExCoveralls],
preferred_cli_env: [
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test
]
Para gerar um relatório HTML, execute o seguinte comando mix coveralls.html no terminal, na raiz do projeto. Isso irá gerar um arquivo HTML dentro da pasta cover/excoveralls.html do projeto, que pode ser aberto em um navegador web para visualização. O relatório mostra quais partes do código foram cobertas pelos testes e quais partes não foram cobertas. Com isso, podemos identificar áreas da aplicação que precisam de mais testes.
Isso define que o ExCoveralls não será executado automaticamente quando os testes forem finalizados (run_at_exit definido como false), que o arquivo de saída JSON será salvo na pasta cover (json_output_path definido como “cover/excoveralls.json”) e que o relatório HTML será gerado na mesma pasta (html_output_dir definido como “cover”).
Aqui nesse ponto vamos perceber que os novos CRUDs de categoria, artigos e comentários estão com problemas nos testes unitários no nível de controle. Para resolver isso basta adicionar um novo método em: test/support/conn_case.ex
def register_and_log_in_user(%{conn: conn}) do
user = user_fixture()
conn = Guardian.Plug.sign_in(conn, user)
{:ok, token, _claims} = Guardian.encode_and_sign(user)
conn = Plug.Conn.put_req_header(conn, "authorization", "Bearer #{token}")
%{conn: conn, user: user}
end
Lembre de definir os alias corretamente no topo de conn_case.ex:
use ExUnit.CaseTemplate
import MyApp.AccountsFixtures
alias MyApp.Accounts.Guardian
Em seguida basta adicionar esse método nos setups dos testes que você for criar de cruds dentro de áreas restritas como no nosso caso as categoria, artigos e comentários. O código vai ficar assim no caso das categorias:
describe "create category" do
setup [:create_category, :register_and_log_in_user]
Com isso os testes vão funcionar corretamente utilizando a sessão criada pelo register_and_log_in_user.
Neste artigo nas partes 1 e 2, vimos como criar uma API RESTful com o Phoenix 1.7, incluindo autenticação e autorização. Criamos um projeto chamado MyApp, onde implementamos os CRUDs de categorias, artigos e comentários, todos relacionados entre si. Utilizamos o banco de dados PostgreSQL, configurado com o Docker, para persistir nossos dados.
Mostramos também como criar o sistema de autenticação para permitir o acesso à API apenas para usuários autenticados, e como configurar todas as rotas necessárias para os nossos CRUDs. Além disso, abordamos a geração de testes automatizados e como verificar a cobertura de testes.
Esperamos que este artigo tenha sido útil para você que deseja aprender mais sobre o Phoenix 1.7 e a construção de APIs com Elixir. A ateliware ama trabalhar com Elixir e o Phoenix em seus projetos, e está sempre de portas abertas para programadores interessados em explorar essas tecnologias. Se você se identifica com a nossa cultura e gostaria de fazer parte da nossa equipe, entre em contato conosco!