ワンクリックで
repositories
Repository pattern for translating between ORM rows and domain entities
メニュー
Repository pattern for translating between ORM rows and domain entities
Request contracts validate input AND map external API names onto domain entities
Domain-Driven Design architecture patterns and conventions for this project
Roar::Decorator representers that turn domain entities into JSON
Presentation layer serializes domain entities to wire formats (JSON, etc.)
How orm/ and repositories/ split responsibility in app/infrastructure/database/
When to use Dry::Struct DTO entities vs. plain Ruby class entities in domain/entities/
| name | repositories |
| description | Repository pattern for translating between ORM rows and domain entities |
Repositories sit between domain entities and the ORM. They are the only
place in the application where Database::*Orm may be referenced outside
of app/infrastructure/database/orm/.
Inline example: ./prompt_logs.rb
Repository::For./for.rb is the single entry point for looking up a repository
from an entity. Every new repository must be registered there:
require_relative '<new_repo>' line at the top of for.rb.Entity::<Name> => <Repos> row to the ENTITY_REPOSITORY map.Callers then resolve a repository in one of two ways:
Repository::For.klass(Entity::PromptLog) # => Repository::PromptLogs
Repository::For.entity(prompt_log_instance) # => Repository::PromptLogs
This keeps services and request objects free of require_relative chains
into the repositories directory — they ask For and get back the right
class. If For.klass returns nil for an entity, the entity is not
persistable; do not add ad-hoc fallbacks at the call site, register it
properly instead.
A repository for Entity::Foo should expose, at minimum:
| Method | Input | Output | Purpose |
|---|---|---|---|
create(entity) | Entity::Foo | persisted Entity::Foo (with id, created_at) | insert |
find_* (e.g. find_all) | filter args | Entity::Foo or Array<Entity::Foo> | query |
rebuild_entity(db_resource) | ORM row or nil | Entity::Foo or nil | shared funnel used by all the above |
Additional methods are added as workflows demand — for example
Repository::PromptLogs.update(id, attrs) exists for partial updates by id.
New methods must still take / return entities (or primitives like id),
never raw ORM rows.
Sequel::Model
instances outward. rebuild_entity is the single funnel that enforces
this.rebuild_entity must defend against nil. Callers rely on it returning
nil cleanly so Repository.update(missing_id, ...) and similar dead-end
lookups do not raise.Tyla::Repository::*, class methods (class << self) —
repositories are stateless.Sequel::Model to a service so the service can call .update
on it. Add a repository method (Repository::PromptLogs.update(id, attrs))
instead.if user.allowed? style decisions inside the repository. Move that to the
service or a policy.