Criando CRUD e relações em API REST no AdonisJS

Série Clone AirBnB com AdonisJS, React Native e ReactJS [Parte 2]

Criando CRUD e relações em API REST no AdonisJS

Esse post é a segunda parte da série de posts “Clone AirBnB com AdonisJS, React Native e ReactJS” onde iremos construir do zero uma aplicação tanto web quando mobile com dados servidos através de uma API REST feita com NodeJS utilizando o framework AdonisJS.

Até agora já temos nosso banco de dados configurado com cadastro e autenticação de novos usuários. Se você não leu o primeiro post deixei um ponto de partida do código pronto aqui: https://github.com/rocketseat/blog-adonis-reactjs-react-native-airbnb/tree/auth.

Nessa segunda etapa iremos criar os seguintes recursos:

  • Listagem de imóveis;
  • Exibição de um único imóvel com imagens;
  • Remoção de imóveis;
  • Relacionamento entre usuários e imóveis (um para muitos);
  • Relacionamento entre imóveis e imagens (um para muitas);
  • (tudo isso utilizando API REST)

Criando models e migrations

Já que estamos falando de uma nova entidade em nossa aplicação (Imóvel), precisamos criar a tabela no banco de dados que irá armazenar esses valores além de criar o seu respectivo model que será usado para realizarmos as ações do ORM como busca, cadastro, edição, remoção, filtros, etc…

Ah, vou manter o padrão de ter tudo em inglês por isso vou chamar o imóvel de “Property” dentro da nossa API.

Para iniciar vamos criar nosso model, migration e controller executando o comando:

adonis make:model Property -m -c

Você receberá um feedback como o seguinte:

 create  app/Models/Property.js
 create  database/migrations/1530569796148_property_schema.js
 create  app/Controllers/Http/PropertyController.js

Wowwww! Acabamos de criar todos os arquivos relacionados à manipulação de imóveis com um único comando!

Agora com a estrutura pronta, vamos adicionar os campos à tabela de imóveis alterando nossa migration (*_property_schema.js) para incluir também os campos:

  • user_id (Referência ao usuário que criou o imóvel);
  • title (Título do imóvel);
  • address (Endereço completo);
  • price (Preço da diária);
  • latitude;
  • longitude;

A maioria dos campos não tem muito segredo mas podemos prestar atenção no campo “user_id” que possui um relacionamento com a tabela de usuários. Além disso, os campos de latitude e longitude são valores decimais com 6 números após a vírgula.

Agora podemos criar nossa tabela no banco de dados com o comando: adonis migration:run.

Pronto, já podemos prosseguir para a criação da nossa segunda migration que criará a tabela no banco responsável por armazenar as imagens de cada imóvel. Como os imóveis poderão ter inúmeras imagens vamos separar isso em outra tabela com novamente um relacionamento 1-N.

Dessa vez não criaremos o controller já que as imagens serão enviadas junto com os demais dados na criação de um imóvel:

adonis make:model Image -m

Agora vamos alterar a migration para conter a referência à tabela de imóveis e também um campo para armazenar o caminho físico da imagem na nossa aplicação:

Relacionamentos no AdonisJS

Agora que configuramos nossas tabelas no banco de dados vamos informar nos nossos models os relacionamentos existentes entre as tabelas para quando realizarmos algum cadastro de informação posteriormente o Adonis ficar sabendo dessas relações.

No arquivo app/Models/User.js vamos começar informando que um usuário pode ter muitos imóveis cadastrados, adicionando um método no fim da classe (não apague código, apenas adicione):

Veja que para criamos um relacionamento no model sempre criamos um novo método retornando uma relação que pode ser “1-N”, “1-1”, “N-N” ou até relacionamentos polimórficos ou mais avançados. Outro ponto é que referenciamos outro model da aplicação em formato de string mesmo.

Agora no model de imóvel vamos adicionar o relacionamento contrário informando que o imóvel sempre pertence a um usuário e aproveitando pra adicionar o relacionamento que um imóvel possui muitas imagens:

Um último caso seria adicionarmos o relacionamento que a imagem pertence à um imóvel, porém nesse caso não é necessário. Isso porque jamais iremos criar a imagem antes para depois relacioná-la com um imóvel, o caminho é sempre inverso, criaremos o imóvel e junto com ele suas imagens, ou seja, não precisamos do relacionamento contrário 🙂

Rotas e controllers

Agora com nossos models devidamente configurados vamos partir para adicionar a lógica do negócio. Todas nossas ações daqui pra frente vão girar em cima do controller de imóvel, por isso, abra o arquivo PropertyController.

Vamos começar removendo dois métodos desse arquivo: create e edit que são funções inúteis em um ambiente de API REST já que servem apenas para exibir os formulários de criação e edição respectivamente, os quais não existem em uma API.

Cada método que sobrou tem uma responsabilidade:

  • index: Listar todos registros;
  • show: Exibir um registro;
  • store: Criar novo registro;
  • update: Alterar um registro;
  • destroy: Remover um registro;

Antes de continuarmos vamos criar as rotas para cada um desses métodos no arquivo start/routes.js. Ao invés de criar uma rota para cada método o Adonis nos oferece um helper chamado resource que pode ser usado da seguinte forma:

Nesse caso estamos informando para o Adonis criar todas as rotas de listagem, exibição, criação, edição e remoção de imóveis em um único comando. O método apiOnly() garante as rotas create e edit que deletamos anteriormente não tenham rota, já o middleware auth vai garantir que usuários não autenticados não possam utilizar essas rotas.

Configurando Insomnia

Para testar a API que estamos desenvolvendo eu deixei um arquivo que você pode importar no seu Insomnia que já contém todos métodos que iremos ter no nosso controller. Basta ir na seção “Import” no Insomnia na opção de “Import from URL” e informar o seguinte endereço: https://raw.githubusercontent.com/Rocketseat/blog-adonis-reactjs-react-native-airbnb/imovel/airbnb-api.json

Pronto, você terá todas as rotas disponíveis na aplicação já com parâmetros fictícios para serem enviados em cada rota. A única coisa que você precisa fazer é se autenticar com um usuário, copiar o token JWT e colar na seção environment do Insomnia:Insomnia EnvironmentVariáveis ambiente no InsomniaAh, você pode alterar a URL também se a sua for diferente ou se estiver testando a API online 🙂

Criando CRUD

Agora vamos botar a mão na massa, se você não conhece o termo CRUD, é uma sigla para (Create, Read, Update, Detele), ou seja, operações básicas em um model. No controller de imóveis adicione a seguinte linha logo após a notação 'use strict' para termos acesso ao model de imóvel dentro do código:

const Property = use('App/Models/Property')

Vou começar com os métodos index, show e destroy que são mais simples e depois partimos para os dois restantes:

Por enquanto vamos apenas retornar todos os imóveis nesse método (mais tarde iremos buscar apenas imóveis próximos baseados na localização do usuário).

Execute no Insomnia a requisição “Index” na pasta “Imóveis”, um array vazio deverá ser retornado.

Nesse momento, seria legal você adicionar manualmente alguns registros de imóveis e imagens de imóveis no seu banco de dados.

O método show possui algumas peculiaridades comparado ao anterior. Nesse caso, podemos acessar os parâmetros enviados na URL (ex: /properties/1) através da variável params e assim buscar exatamente o registro no banco com esse ID.

Logo após, executamos o método load para fazer o carregamento de um relacionamento do model, dessa forma, nossa API retornará também as imagens do imóvel buscado.

Executando a ação “Show” na pasta “Imóvel” no Insomnia obteremos um erro HTTP já que não temos nenhum imóvel cadastrado, mas você pode experimentar cadastrar um imóvel com imagens e terá um resultado semelhante a esse:Resposta API AdonisJSAgora, o último método que faremos nesse post é o destroy que serve para deletar um registro:

Esse método por sua vez novamente busca o imóvel através do parâmetro ID da URL e faz uma verificação se o dono do imóvel é o mesmo usuário tentando fazer a requisição, caso contrário não permite a operação retornando a mensagem:Erro 401 APINo fim, caso validado, o imóvel é deletado.

Mais um passo

Nesse post dêmos mais um passo para a finalização da nossa aplicação completa com AdonisJS, ReactJS e React Native e agora estamos enxergando cada vez mais como será realizada a comunicação entre essas plataformas utilizando nossa API REST.

Código desse post: https://github.com/Rocketseat/blog-adonis-reactjs-react-native-airbnb/tree/imovel

Para o próximo post dessa série nós vamos mais a fundo na nossa API construindo as seguintes funcionalidades:

  • Criação/edição de imóveis com upload;
  • Busca por distância através de GPS;

Se você está curtindo essa série não esquece de deixar um comentário aí em baixo pra eu ficar sabendo e claro, todas dúvidas também podem aparecer aí nos comentários 🙂

spinner_vs_shimmer
A seguir:

Implementando Shimmer Effect no React Native

Implementando Shimmer Effect no React Native