Voltar

E-commerce Admin Part I - Iniciando API com Rails, Models e Associações

Construindo API em Ruby on Rails e entendendo mais sobre as Entidades do projeto ecommerce
12 de março de 2023 às 19:02

Contexto e conhecendo o projeto

Este projeto está sendo desenvolvido dentro de um bootcamp fullstack, criado pela Onebitcode, que tem como objetivo final desenvolver tanto o backend como frontend (web e mobile) de um ecommerce em venda de licença de jogos (chaves). Nesta publicação irei fazer um resumo de partes essenciais do meu aprendizado nos módulos iniciais do curso focado no desenvolvimento da API utilizando Ruby on Rails. Nesses primeiros módulos construímos a parte do backend voltado para o administrativo do negócio. A estrutura é toda planejada com algumas aulas excelentes explicando o planejamento do banco de dados, os endpoints necessários, mockups e muitos dos requisitos que vão ser importantes para o desenvolvimento.

Entidades

Em um projeto de alta complexidade como um ecommerce é esperado que existam diversas entidades que se ligam formando relacionamentos importantes entre eles para que obtenhamos informações ricas que vão gerar valor para o ecommerce como um produto.

  • Categories (Categorias de jogos)
  • Users
  • System Requirements
  • Coupons
  • Licenses
  • Products
  • Games

O que vai ser utilizado/instalado no projeto?

  • Ruby 2.7.1
  • Rails 6.0.3.3
  • Envio de email com Mailcatcher
  • Autenticação com Devise Token Auth na qual utiliza uma técnica de login que recebe usuário e senha para retornar um token para o usuário. A cada request que o usuário envia, ele vai receberá a resposta e um novo token para utilizar no próximo request.
  • RSpec como ferramenta de testes. Embora o Rails venha com o Minitest embutido, o RSpec possui uma larga adoção e se tornou um padrão de mercado e este curso foca na utilização dele.

Criando model de Categoria

O model Category é bem simples, possui apenas um campo name e pode ser criado dentro do rails com apenas um comando:

rails g model Category name

Quando executamos esse comando, criamos quatro arquivos: uma migration, a factory do model, o teste do model e o model em si. Após a criação do model, devemos rodar a migration para seja criado de fato dentro do banco de dados.

rails db:migrate

Seguindo como base o desenvolvimento baseado em testes, criamos os testes para o model de categoria criado.

require "rails_helper"

RSpec.describe Category, type: :model do
  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_uniqueness_of(:name).case_insensitive }
end

Neste teste validamos a presença do campo name e sua unicidade dentro da tabela, já o model em si ficaria assim

class Category < ApplicationRecord
  validates :name, presence: true, uniqueness: { case_sensitive: false }
end

Model polimórfico

A entidade de Produto será polimórfica, ou seja, terá um associação polimórfica. A associação polimórfica é um conceito importante na programação orientada a objetos que permite que um objeto possa ser associado a outros objetos de diferentes tipos, sem que isso dependa de uma classe específica. Em outras palavras, um objeto pode ter múltiplas associações com outros objetos que implementam uma determinada interface ou classe abstrata. A principal vantagem da associação polimórfica é que ela permite maior flexibilidade e modularidade no design de software.

Criaremos Product como polimórfico porque, embora atualmente tenhamos apenas jogos, ele pode ter diferentes tipos no futuro. Isso significa que o produto deve ser capaz de pertencer a mais de um modelo. Com isso, podemos concentrar a responsabilidade do produto em uma entidade própria e permitir que, no futuro, possamos adicionar mais tipos além de jogos. A abordagem polimórfica nos permite ter mais flexibilidade e escalabilidade em nosso sistema, garantindo que possamos adicionar novas funcionalidades sem precisar modificar a estrutura básica do nosso código

rails g model Product name description:text "price:decimal{10,2}" productable:references{polymorphic}

Com model criado, criamos os testes de validação de tal model. As mesmas validações de presença de alguns campos, unicidade e validação de valor númerico maior que zero para price. Além, desse é adicionado aqui também o teste belong_to que faz a validação das associações feitas no model.

RSpec.describe Product, type: :model do
  it { is_expected.to belong_to :productable }
  it { is_expected.to validate_presence_of(:name) }
  it { is_expected.to validate_uniqueness_of(:name).case_insensitive }
  it { is_expected.to validate_presence_of(:description) }
  it { is_expected.to validate_presence_of(:price) }
  it { is_expected.to validate_numericality_of(:price).is_greater_than(0) }
end

Com os testes criado e falhando, podemos adicionar todas essas validações no model de Product e avaliar que todas passaram nos testes.

class Product < ApplicationRecord
  belongs_to :productable, polymorphic: true

  validates :name, presence: true, uniqueness: { case_sensitive: false }
  validates :description, presence: true
  validates :price, presence: true, numericality: { greater_than: 0 }
end

Entidade Associativa ProductCategory

Este model é uma entidade associativa, criada especificamente para permitir a associação entre dois outros modelos: Produto e Categoria. Na prática, uma entidade associativa é uma tabela (ou uma classe) que representa o relacionamento entre duas ou mais entidades, sendo responsável por armazenar os identificadores (ou referências) dessas entidades. Por exemplo, considere um sistema de vendas online onde temos duas entidades: "Clientes" e "Produtos". Para representar a compra de um produto por um cliente, podemos criar uma entidade associativa chamada "Compras" que armazena o identificador do cliente, o identificador do produto e outras informações relevantes, como data da compra e valor pago.

As entidades associativas são úteis porque permitem representar relacionamentos muitos-para-muitos (N x N) entre entidades, que não podem ser diretamente modelados sem a criação de uma entidade intermediária. Além disso, elas fornecem uma maneira eficiente de consultar informações relacionadas entre duas ou mais entidades.

Em resumo, as entidades associativas são uma ferramenta importante em programação e bancos de dados para modelar relacionamentos complexos entre entidades. Elas permitem representar associações N x N e fornecem uma maneira eficiente de consultar informações relacionadas entre as entidades.

Comando para criar tal model:

rails g model ProductCategory product:references category:references

Teste para ProductCategory

RSpec.describe ProductCategory, type: :model do
  it { is_expected.to belong_to :product }
  it { is_expected.to belong_to :category }
end

Validações no model de ProductCategory

class ProductCategory < ApplicationRecord
  belongs_to :product
  belongs_to :category
end