con un clic
requests
Request contracts validate input AND map external API names onto domain entities
Menú
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.)
Repository pattern for translating between ORM rows and domain entities
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 | requests |
| description | Request contracts validate input AND map external API names onto domain entities |
app/application/requests/ is the only layer that is allowed to know
about external API field names. By the time data leaves this layer, every
field is named in the domain's vocabulary.
Live contracts in this folder: ./guard_check.rb and
./tutor_chat.rb. Both validate only; their services build
the domain entity inline (they enrich it with LLM output, so a pure to_entity
mapping does not apply). The to_entity half below is the convention for a
plain request → entity mapping with no enrichment.
A Request::* class has two jobs. They live in one file so the API
boundary stays in one place:
Dry::Validation::Contract.Entity::* via a class method
self.to_entity(validated_hash).# Validate
contract = Request::Example.new
result = contract.call(r.params)
r.halt(422, ...) unless result.success?
# Map — external names die here
entity = Request::Example.to_entity(result.to_h)
saved = Repository::Examples.create(entity)
External API names (userPrompt, attack-probability, camelCase /
hyphenated / snake_case mixes, whatever the caller uses) appear only
inside this file (and any wire-format key normalisation in the route,
e.g. hyphen → underscore before validation):
params do ... end block as required keysto_entity mapping tableAfter to_entity returns, the rest of the codebase only sees domain names
(prompt, attack_probability, evaluation).
r.params[:userPrompt] in a route or service. The route hands
the validated hash straight to to_entity. External names must die
there.Entity::* from a request hash in a service. If that
conversion is needed, add a class method on the request and call it from
the route.