Criando uma API com Phoenix Framework/Elixir

Carlos Morette
Cumbuca
Published in
5 min readMar 30, 2022

--

O que é o Phoenix Framework?

Phoenix é um framework para criação de aplicações web usando Elixir. É amplamente usado para criação de aplicações SSR (renderização do lado do servidor), API’s e muito mais. Nesse post iremos criar uma API REST que faz um CRUD de usuário. Caso queria ver o projeto completo, está disponibilizado no GitHub.

Inclusive, usamos o Phoenix para criar e manter nosso back-end aqui na Cumbuca. Da uma olhadinha no post do nosso CTO Castilho que explica “Por que escolhemos Elixir”.

Pré-requisito

Para conseguir criar a API sem problemas você precisa ter o Elixir e o PostgreSQL (banco relacional que iremos armazenar dados) instalados em seu computador. Caso esteja tudo ok, bora começar!

Criando projeto

Para a criação vamos usar tarefa que o próprio Phoenix disponibiliza que é a phx.new:

mix phx.new my_api

Tarefas são scripts criados para realizar alguma coisa dentro do ambiente Elixir. Por exemplo, temos a new que cria um projeto em Elixir. E a phx.new cria um projeto Phoenix.

Migração

Para não precisarmos entrar no terminal do PostgreSQL e executar nossos comandos DDL, podemos simplesmente criar um arquivo com migrações que o Ecto irá executar. O comando abaixo irá criar uma migração chamada create_users_table em: priv/repo/migrations.

mix ecto.gen.migration create_users_table

Coloquemos a criação da tabela e seus respectivos campos no arquivo que foi gerado no caminho dito no parágrafo anterior (vamos executar nossa migração no final do post, quando estiver tudo pronto):

Criação do schema

O schema serve como um descritor de entidade, na qual expõe dados e seus respectivos campos. Agora criaremos um que irá descrever nossa tabela users do banco.

Crie o módulo responsável pelo schema do usuário e funções auxiliares em lib/my_api/user.ex.

Em seguida criaremos funções que irão listar, inserir, atualizar e deletar usuários. Seu arquivo ficará assim:

Para assegurar a consistência dos dados usamos o changeset. Em poucas palavras changeset é um módulo da biblioteca Ecto que nos fornece funções para identificar dados inconcisos antes de tentarmos usá-los, e para seguir o padrão, nós criamos uma função changeset que receberá um usuário, seus atributos e validá-los.

Depois de criar o changeset criamos funções que irão fazer as operações no banco de dados. Nas funções update/2 e delete/1 chamamos find_by_id/1 para verificar se o usuário existe, caso não, devolvemos uma tupla indicando que o usuário não foi encontrado.

É comum usarmos tuplas em elixir para deixar o código semântico, geralmente quando algo da certo, retornamos :ok, ou {:ok, alguma_coisa} e quando da errado retornamos {:error, razao_do_erro}. Isso é uma das práticas que facilita a legibilidade de códigos em Elixir.

Bom, até agora criamos a camada de negócio e manipulação dos dados, vamos para a parte web e comecemos a criar nosso controller que irá orquestrar as requisições.

Controller

Criemos o arquivo lib/my_api_web/controllers/user_controller.ex com a função show/2, que receberá o método GET, colocará o status da resposta para Ok (200) e chamará uma view passando todos os usuários que buscamos do banco.

defmodule MyApiWeb.UserController do
use MyApiWeb, :controller

def show(conn, _params) do
conn
|> put_status(:ok)
|> render("index.json", users: MyApi.User.get_all())
end
end

Antes de criarmos outras funções, vamos criar nossa view em lib/my_api_web/views/user_view.ex com o seguinte conteúdo:

Criamos duas funções render, a primeira irá receber uma lista de usuários e delegar a renderização para a segunda função render que recebe um usuário por vez. Como pode ver, estamos usando patten matching para ter duas funções com mesmo nome só que cada uma tem uma responsabilidade diferente.

Bom, agora que temos o método GET vamos adicionar os demais métodos. Seu controller ficará dessa forma:

Na função create/2 pegamos os dados que vem no corpo da requisição e passamos para nossa função MyApi.Users.insert/1. Lembrando que o changeset do Ecto retorna uma mensagem de erro dizendo que alguma chave está faltando, previmos esse caso e colocamos ‘_’ para ignorar sua mensagem de erro, caso a inserção do usuário seja bem sucedida, devolvemos Created (201) e o usuário criado.

Em update/2 repetimos o processo passando o ID do usuário que irá vir nos parâmetros da requisição. Caso não exista o usuário retornamos Not Found (404). Em delete/2 fazemos a mesmo coisa, apenas mudamos a função que é chamada.

Agora que temos nosso controlador funcionando, vamos adicionar nossas rotas em lib/my_api_web/router.ex:

No código acima estamos criando um escopo com o caminho “/api”, que irá sempre buscar o controller em MyApiWeb. Em seguida invocamos o pipeline :api. Criamos nossas respectivas rotas com seus métodos: GET, POST, PUT e DELETE cada uma apontando para o controlador UserController invocando sua respectiva função: :show, :create, :update, :delete.

Você deve estar se perguntando o que é um pipeline e um plug? Em palavras simples:

  • Pipeline: Alinhadores de plugs, com ele podemos criar um funil com vários deles, cada um passando seu resultado para o próximo até o final.
  • Plug: Pense nele como um pedaço de código que vai receber uma estrutura de dados, fazer algo e devolver essa estrutura com as transformações feitas. Geralmente utilizamos plug para fazer validações e adicionar dados na requisição.

Testando

Agora que está tudo pronto! Podemos testar nossa api. Antes de tudo, vamos rodar uma tarefa que vai configurar todo o ambiente para nós:

mix ecto.setup

Essa tarefa irá:

  1. Obter todas as bibliotecas que estão definidas em mix.exs.
  2. Criar o banco de dados do projeto.
  3. Rodar as migrações.

Após ter feito o setup, vamos rodar o projeto! Rode o comando e sua api vai estar ativa em seu localhost escutando na porta 4000:

mix phx.server

Para essa parte irei usar o Insomnia, mas você pode usar a ferramenta que desejar, como curl e Postman.

Vamos criar um usuário:

Print mostrando cadastro de usuário na API.

Vamos mostrar os usuários existentes:

Print mostrando exibição de usuários na API.

Vamos atualizar nosso usuário criado:

Vamos ver como ele ficou com seu “Novo nome”:

Print mostrando exibição de usuários na API.

Agora deletemos ele:

Print mostrando deleção de usuário na API.

Esse foi o post de hoje e espero ter ajudado caso você seja um iniciante em Elixir. E caso não esteja convencido do por que usar Elixir, tenho um post falando do Por que você deveria gostar de Elixir? Onde eu falo os principais motivos para eu gostar tanto dessa linguagem que vem crescendo nos últimos tempos.

Se você ficou com vontade de fazer parte do nosso time ou conhecer mais sobre a nossa cultura, veja a nossa página de carreiras!

--

--