Roteamento e versionamento
Versionado na URL
Toda rota vive sob /api/v1/... — config/routes.rb:
namespace :api do
namespace :v1 do
namespace :auth do
get :me, to: "me#show"
patch :me, to: "me#update"
end
get "c_configuracoes/atual", to: "c_configuracoes#atual"
namespace :admin do
resources :c_configuracoes
resources :a_papeis
# ...
resources :versions, only: %i[index show]
end
end
end
O número na URL (v1) é a estratégia de versionamento inteira — não tem
header de versão nem content negotiation por Accept. Simples de propósito:
enquanto só existe uma versão, a URL versionada já é suficiente pra abrir
caminho pra uma v2 no futuro sem quebrar quem já integra com v1, sem
precisar de infraestrutura de negociação que ninguém usa ainda.
admin vs. auth — dois perfis de rota bem separados
namespace :admin agrupa todo CRUD que exige sessão e autorização
granular (resources :a_papeis, resources :versions, etc. — um recurso
por linha, RESTful puro, sem rota customizada além do que resources já
gera). namespace :auth é a exceção: rotas de sessão e perfil próprio
(GET/PATCH /api/v1/auth/me), que fazem sentido fora do padrão CRUD
porque não são "um recurso entre muitos", são sobre o usuário autenticado
em si. O login/logout em si (devise_for :users) fica montado à parte,
não dentro de namespace :api — ver
Autenticação.
O catch-all tem que ficar dentro do namespace
namespace :api do
namespace :v1 do
# ...
end
match "*unmatched", to: "/errors#not_found", via: :all
end
Achado real, não teórico: um catch-all (match "*unmatched", ...) puxado
pra fora de namespace :api, na raiz do arquivo de rotas, quebrava a
resolução de URL do ActiveStorage — rotas do Rails que também vivem na
raiz passavam a cair no catch-all antes de chegar na rota real delas. A
correção foi simplesmente manter o catch-all como o último item
dentro do próprio namespace :api, escopado só ao que já é /api/* —
ele nunca compete com rota de fora da API. /errors#not_found devolve o
mesmo envelope de erro de qualquer outro 404 (ver
Tratamento de erros),
então uma URL de API inexistente nunca cai na página de erro HTML padrão
do Rails.
Leitura de apoio
- Rails Routing from the Outside In (docs oficiais) —
namespace,resources, rota catch-all. - REST API versioning: URI vs. header — comparação entre versionar na URL (o que este projeto faz) e por header/content negotiation.

