A fronteira que já existe
O padrão repositório serve para manter o acesso a dados longe de todo o resto. Antes de julgá-lo, meça quanto disso esta aplicação já tem. Os números abaixo foram medidos em 28/09/2026.
A medição
objetos de consulta: 58
dos quais definem um Result de Data: 51
chamadas do ActiveRecord em views: 0
chamadas do ActiveRecord em controllers: 22
objetos de serviço: 55
Não há acesso a dados na camada de view, em nenhum dos 100 templates. É esse o resultado que costuma vender o padrão repositório, e esta aplicação chegou a ele sem repositório.
Vinte e duas chamadas ficam em controllers, em 57 arquivos de controller. A lição 5 as separa por tipo.
Como é um objeto de consulta aqui
module Catalog
class ListCoursesQuery
Result = Data.define(:courses_by_level, :lesson_counts, :total_counts_by_level)
def self.call(authenticated: true)
courses = ::Catalog::Course.active.ordered.includes(:category)
...
end
end
end
Um método de classe, argumentos nomeados e um objeto Data como retorno. Cinquenta e um dos cinquenta e oito seguem esse formato, e nenhum devolve uma relação.
A parte que não é o que parece
O courses_by_level guarda registros de Catalog::Course. O objeto Data é um contêiner para models do ActiveRecord e não os substitui.
Isso é de propósito. O MEMORY.md diz com todas as letras:
"Consultas precisam devolver objetos Data puros ou Arrays de Models do ActiveRecord. São operações puramente de Domínio e nunca devem conter lógica de apresentação, formatação de HTML, ou roteamento de URL."
A regra proíbe lógica de apresentação e permite ActiveRecord. É uma posição clara, e diferente da do padrão repositório. As duas se confundem com frequência, por isso vale deixar claro.
flowchart TB
V["views: 0 chamadas de acesso a dados"] --> B["a fronteira que importa"]
C["controllers: 22 chamadas em 57 arquivos"] --> B
Q["58 objetos de consulta, 51 com Result de Data"] --> B
Q --> N["o objeto Data contém models do ActiveRecord"]
N --> P["uma fronteira de formato, não de persistência"]
Duas fronteiras diferentes
Essa distinção atravessa o curso inteiro.
Uma fronteira de formato define o que quem chama recebe: três campos nomeados, em vez do que um controller por acaso atribuiu. Quem chama não alcança nada que não tenha recebido, e o contrato da consulta cabe numa linha.
Uma fronteira de persistência esconde de quem chama a origem dos dados. Ela devolve objetos de domínio sem save, sem where e sem associações para percorrer.
Esta aplicação tem a primeira em todo lugar e a segunda em lugar nenhum. Um controller com courses_by_level na mão tem registros de Course, e poderia chamar .update! em qualquer um.
O que cada uma entrega
| Fronteira de formato | Fronteira de persistência | |
|---|---|---|
| Acesso a dados fora das views | Sim | Sim |
| O contrato da consulta é legível | Sim | Sim |
| Quem chama pode percorrer para qualquer coisa | Sim, pode | Não |
| Trocar o ORM | Não | Em princípio |
| Testar o domínio sem banco | Não | Sim |
| Custo | Uma linha de Data.define |
Uma camada de mapeamento por agregado |
A maioria dos times quer as duas primeiras linhas, e um objeto de consulta já as entrega de graça.
As linhas três, quatro e cinco são território do padrão repositório. A lição 2 pergunta quanto vale cada uma numa aplicação Rails, porque as respostas mudam em relação à linguagem para a qual o padrão foi escrito.
Onde isso deixa a base de código
Esta base resolveu o problema do padrão repositório com uma ferramenta mais barata e abriu mão de uma propriedade.
Qual: um Course entregue a um controller continua sendo um Course. Ele é mutável, dá para percorrer suas associações e segue ligado ao banco. Se isso importa é a pergunta em aberto, e as lições 3 a 6 respondem de quatro jeitos.
A medição, essa não está em discussão. Nenhum acesso a dados em 100 templates é uma fronteira real, e quem a garantiu foi uma convenção, não uma abstração.
Pontos-chave
- Medido em 28/09/2026: 58 objetos de consulta, 51 com Result de
Data, 0 chamadas de acesso a dados em views, 22 em controllers. - O Result de
Datacontém models do ActiveRecord. É fronteira de formato, não de persistência. - O
MEMORY.mdproíbe lógica de apresentação em consultas e permite explicitamente devolver models. - Uma fronteira de formato dá contratos legíveis e tira o acesso a dados das views. Uma de persistência esconde o ORM.
- Esta base tem a primeira em todo lugar e a segunda em lugar nenhum, por convenção e não por abstração.
Continue com a aula 2
O que o padrão promete
Revisa as quatro promessas do padrão e o atrito de empilhar Data Mapper sobre Active Record no Rails.
Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.