Modelagem base

· Padrão Banco de Dados
Juan Kalleo
Juan Kalleo
Backend/API
This page hasn't been translated to English yet — showing the original Portuguese content.

Todo model deste projeto herda de ApplicationRecord — e ganha, sem precisar declarar nada, quatro comportamentos que normalmente seriam reimplementados (ou esquecidos) model a model.

O que vem de graça

class ApplicationRecord < ActiveRecord::Base
  primary_abstract_class

  include Auditable
  acts_as_paranoid
  has_paper_trail

  before_validation :garantir_public_id
  before_save :set_paper_trail_whodunnit

  MAX_STRING_LENGTH = 255
  MAX_TEXT_LENGTH = 10_000
  validate :limitar_tamanho_dos_campos_de_texto
end

Auditoria — quem mudou, quando, de onde

O concern Auditable (app/models/concerns/auditable.rb) preenche created_by/updated_by a partir de Current.user a cada create/save, e deleted_by no soft delete (ver abaixo) — sem precisar de callback manual em cada model. Current é um ActiveSupport::CurrentAttributes, resolvido uma vez por requisição (ver Envelope de resposta pro lado da API que popula isso).

Soft delete por padrão — não opcional

acts_as_paranoid

Toda tabela tem uma coluna deleted_at; "excluir" um registro marca essa coluna, não remove a linha. Consultas normais (Model.all, Model.find) já ignoram registro soft-deletado automaticamente — só um escopo explícito (Model.only_deleted/.with_deleted) enxerga ele. Pra um User, isso tem um efeito prático direto: um usuário soft-deletado simplesmente não é encontrado por find_for_authentication, então não consegue logar — o mesmo efeito prático de um campo ativo: false, sem precisar de uma coluna de status separada só pra isso.

Versionamento — todo model, sem opt-out

has_paper_trail

def set_paper_trail_whodunnit
  PaperTrail.request.whodunnit = Current.user&.id&.to_s
end

Toda mudança (create/update/destroy) de todo model grava uma linha na tabela versions, com quem fez (whodunnit) e o estado anterior do registro. É o que sustenta Logs de auditoria no Padrão Frontend. Detalhe completo da tecnologia em PaperTrail.

Limite de tamanho de campo — reforçado no ORM, não só no banco

MAX_STRING_LENGTH = 255
MAX_TEXT_LENGTH = 10_000
validate :limitar_tamanho_dos_campos_de_texto

Toda coluna :string tem teto de 255 caracteres, toda :text tem teto de 10.000 — reforçado por validação no model, não só pelo tipo de coluna do banco (que em Postgres, sem limit: explícito, não impõe teto nenhum). Isso garante o teto mesmo se alguém pular a camada de validação do front e mandar payload direto pra API.

public_id — opt-in, não automático

before_validation :garantir_public_id

Só preenche um UUID se a tabela tiver a coluna public_id — não adiciona a coluna sozinho. public_id existe só nas tabelas cujo registro é exposto publicamente (URL, referência externa) — usar UUID em vez do id numérico sequencial nesses casos evita que alguém enumere registro só incrementando um número na URL (ver IDOR e autorização no Padrão Frontend, o mesmo princípio do lado do front).

Leitura de apoio