R-003 — Slug de organização e produto vem do nome e não muda depois
TLDR:
organizations.slugeproducts.slugsão gerados donameviaparameterize, sem limite de tamanho, e congelados depois de gravados. Único global nos dois — organização e produto.
Given / When / Then
Dado uma organização ou produto sendo salvo com slug em branco,
Quando o registro é validado,
Então o slug recebe o name passado por parameterize, sem truncamento.
Dado o slug preenchido à mão,
Quando o registro é validado,
Então o valor é normalizado pela mesma regra, em vez de ser aceito como veio.
Dado um registro que já tem slug gravado,
Quando o name muda,
Então o slug permanece o mesmo — é identificador estável para o ibft-backend resolver.
Dado um slug já usado no escopo de unicidade,
Quando outro registro é validado com o mesmo slug,
Então o registro é inválido e errors[:slug] é preenchido.
Tabela de decisão
| Entidade | name |
slug |
Válido? |
|---|---|---|---|
| Organization | Curso de Inglês |
curso-de-ingles |
✅ |
| Organization | Curso v1.0 |
curso-v1-0 |
✅ |
| Organization | Curso A 1, com curso-a-1 existente |
curso-a-1 |
❌ colisão global |
| Product (org X) | Curso A 1, com curso-a-1 na org X |
curso-a-1 |
❌ colisão global |
| Product (org Y) | Curso A 1, com curso-a-1 na org X |
curso-a-1 |
❌ colisão global — mesmo em org diferente |
| Organization | @@@ |
"" |
✅ allow_blank |
Restrições
- Coluna anulável e sem validação de presença: organização sem slug simplesmente não sincroniza.
- Sem limite de tamanho:
Slugablenão tem opção de truncamento, é o mesmo concern usado porCheckouteCustomFieldOption, sem tratamento especial para organização e produto. - Colisão é erro de validação em registro novo, mas o backfill da migration resolve com sufixo
-2/-3— lá não há operador para corrigir.
Teste vinculado
spec/models/organization_spec.rb / spec/models/product_spec.rb — bloco describe "slug": derivação, normalização, estabilidade no rename e colisão (única global nos dois, mesmo em organizações diferentes).
Referências
- ../../specs/20260909143000_organization_product_slug.md — decisões, alternativas descartadas e escopo da fase 1
- ../../reference/payments/new_checkout_repayment_endpoint.md — regra canônica replicada para o
ibft-backend