You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/basics/validation.es.md
+60
Original file line number
Diff line number
Diff line change
@@ -227,3 +227,63 @@ Los validadores también pueden combinarse mediante operadores para construir va
227
227
|`!`|prefijo|Invierte un validador, requiriendo lo opuesto.|
228
228
|`&&`|infijo|Combina dos validadores, requiere ambos.|
229
229
|`||`|infijo|Combina dos validadores, requiere al menos uno.|
230
+
231
+
## Validadores Personalizados
232
+
233
+
Crear un validador personalizado para códigos postales te permite extender la funcionalidad del marco de validación. En esta sección, te guiaremos a través de los pasos para crear un validador personalizado que valide códigos postales.
234
+
235
+
Primero, crea un nuevo tipo para representar los resultados de la validación de `ZipCode`. Esta estructura será responsable de informar si una cadena dada es un código postal válido.
236
+
237
+
```swift
238
+
extensionValidatorResults {
239
+
/// Representa el resultado de un validador que verifica si una cadena es un código postal válido.
240
+
publicstructZipCode {
241
+
/// Indica si la entrada es un código postal válido.
242
+
publiclet isValidZipCode: Bool
243
+
}
244
+
}
245
+
```
246
+
247
+
A continuación, haz que el nuevo tipo cumpla con `ValidatorResult`, que define el comportamiento esperado de un validador personalizado.
Finalmente, implementa la lógica de validación para los códigos postales. Usa una expresión regular para verificar si la cadena de entrada coincide con el formato de un código postal de EE.UU.
Ahora que has definido el validador personalizado `zipCode`, puedes usarlo para validar códigos postales en tu aplicación. Simplemente agrega la siguiente línea a tu código de validación:
286
+
287
+
```swift
288
+
validations.add("zipCode", as: String.self, is: .zipCode)
Copy file name to clipboardexpand all lines: docs/fluent/model.es.md
+7-5
Original file line number
Diff line number
Diff line change
@@ -359,12 +359,14 @@ app.get("planets") { req async throws in
359
359
360
360
Al serializar desde/hacia `Codable`, las propiedades del modelo usarán sus nombres de variable en lugar de las claves. Las relaciones serán serializadas como estructuras anidadas y cualquier carga previa (eager loading) de datos será incluida.
361
361
362
+
!!! info "Información"
363
+
Recomendamos que para casi todos los casos utilices un DTO en lugar de un modelo para tus respuestas de API y los cuerpos de tus solicitudes. Consulta [Objeto de transferencia de datos](#data-transfer-object) para obtener más información.
364
+
362
365
### Data Transfer Object
363
366
364
-
La conformidad por defecto del modelo a `Codable` puede facilitar el prototipado y usos simples. Sin embargo, no se ajusta a todos los casos de uso. Para ciertas situaciones necesitarás usar un data transfer object (DTO).
367
+
La conformidad por defecto del modelo a `Codable` puede facilitar el prototipado y usos simples. Sin embargo, expone la información subyacente de la base de datos a la API. Esto generalmente no es deseable desde un punto de vista de seguridad —devolver campos sensibles como el hash de la contraseña de un usuario es una mala idea— y desde una perspectiva de usabilidad. Hace difícil cambiar el esquema de la base de datos sin romper la API, aceptar o devolver datos en un formato diferente, o agregar o eliminar campos de la API.
365
368
366
-
!!! tip "Consejo"
367
-
Un DTO es un tipo `Codable` aparte que representa la estructura de datos que quieres codificar/descodificar.
369
+
En la mayoría de los casos, deberías usar un DTO o data transfer object (objeto de transferencia de datos) en lugar de un modelo (también conocido como domain transfer object). Un DTO es un tipo `Codable` separado que representa la estructura de datos que deseas codificar o decodificar. Esto desacopla tu API del esquema de la base de datos y te permite realizar cambios en tus modelos sin romper la API pública de tu aplicación, tener diferentes versiones y hacer que tu API sea más agradable de usar para tus clientes.
368
370
369
371
Toma como base el siguiente modelo de `User` para los ejemplos a continuación.
Aunque la estructura del DTO sea idéntica a la del modelo conformado con `Codable`, tenerlo como tipo aparte puede ayudar a mantener los proyectos grandes ordenados. Si necesitaras hacer un cambio en las propiedades de tu modelo, no tienes que preocuparte de si rompes la API pública de tu app. Puedes considerar agrupar tus DTO en un package aparte que puedas compartir con los consumidores de tu API.
439
+
Otro caso de uso común es al trabajar con relaciones, como relaciones de padre o de hijos. Consulta [la documentación de Parent](relations.es.md#codificación-y-decodificación-de-relaciones-parent) para ver un ejemplo de cómo usar un DTO para facilitar la decodificación de un modelo con una relación `@Parent`.
438
440
439
-
Por estas razones, recomendamos encarecidamente usar DTO siempre que sea posible, especialmente en proyectos grandes.
441
+
Incluso si la estructura del DTO es idéntica a la conformidad `Codable` del modelo, tenerlo como un tipo separado puede ayudar a mantener organizados los proyectos grandes. Si alguna vez necesitas realizar un cambio en las propiedades de tus modelos, no tendrás que preocuparte por romper la API pública de tu aplicación. También puedes considerar colocar tus DTOs en un paquete separado que pueda ser compartido con los consumidores de tu API y agregar conformidad a `Content` en tu aplicación Vapor.
### Codificación y Decodificación de Relaciones Parent
65
+
66
+
Algo a tener en cuenta al trabajar con relaciones `@Parent` es la forma en que se envían y reciben. Por ejemplo, en JSON, una relación `@Parent` para un modelo `Planet` podría verse así:
67
+
68
+
```json
69
+
{
70
+
"id": "A616B398-A963-4EC7-9D1D-B1AA8A6F1107",
71
+
"star": {
72
+
"id": "A1B2C3D4-1234-5678-90AB-CDEF12345678"
73
+
}
74
+
}
75
+
```
76
+
77
+
Nota cómo la propiedad `star` es un objeto en lugar del ID que podrías esperar. Al enviar el modelo como un cuerpo HTTP, debe coincidir con esta estructura para que la decodificación funcione. Por esta razón, recomendamos encarecidamente usar un DTO para representar el modelo al enviarlo por la red. Por ejemplo:
78
+
79
+
```swift
80
+
structPlanetDTO: Content {
81
+
var id: UUID?
82
+
var name: String
83
+
var star: Star.IDValue
84
+
}
85
+
```
86
+
87
+
Luego puedes decodificar el DTO y convertirlo en un modelo:
88
+
89
+
```swift
90
+
let planetData =try req.content.decode(PlanetDTO.self)
91
+
let planet =Planet(id: planetData.id, name: planetData.name, starID: planetData.star)
92
+
tryawait planet.create(on: req.db)
93
+
```
94
+
95
+
Lo mismo aplica al devolver el modelo a los clientes. Tus clientes deben poder manejar la estructura anidada o necesitas convertir el modelo en un DTO antes de devolverlo. Para más información sobre los DTOs, consulta la [documentación del modelo](model.es.md#data-transfer-object).
96
+
64
97
## Optional Child
65
98
66
99
La propiedad `@OptionalChild` crea una relación uno a uno entre dos modelos. No guarda ningún valor en el modelo raíz.
@@ -284,7 +317,7 @@ Ver [query](query.md) para más información.
284
317
285
318
## Eager Loading
286
319
287
-
El constructor de consultas (query builder) de Fluent te permite precargar las relaciones de un modelo cuando es recuperado de la base de datos. Esto se conoce como "eager loading" y te permite acceder a las relaciones de manera sincrónica sin la necesidad de llamar previamente a [`load`](#lazy-eager-loading) o [`get`](#get) .
320
+
El constructor de consultas (query builder) de Fluent te permite precargar las relaciones de un modelo cuando es recuperado de la base de datos. Esto se conoce como "eager loading" y te permite acceder a las relaciones de manera sincrónica sin la necesidad de llamar a [`get`](#get) primero.
288
321
289
322
Para hacer un "eager load" de una relación, pasa un key path a la relación con el método `with` en el constructor de consultas.
290
323
@@ -311,6 +344,7 @@ for planet in planets {
311
344
En el ejemplo anterior, se le ha pasado un key path a la relación [`@Parent`](#parent) llamada `star` con `with`. Esto provoca que el constructor de consultas haga una consulta adicional después de cargar todos los planetas para recuperar todas las estrellas conectadas a éstos. Las estrellas son accesibles de manera sincrónica mediante la propiedad `@Parent`.
312
345
313
346
Cada relación precargada (eager loaded) necesita una única consulta adicional, sin importar cuántos modelos se hayan devuelto. La precarga (eager loading) sólo es posible con los métodos de constructor de consultas `all` y `first`.
347
+
314
348
### Nested Eager Load
315
349
316
350
El método de constructor de consultas `with` te permite precargar relaciones en el modelo que está siendo consultado. Sin embargo, también puedes precargar relaciones en los modelos conectados.
@@ -330,16 +364,23 @@ El método `with` acepta un closure opcional como segundo parámetro. Este closu
330
364
331
365
## Lazy Eager Loading
332
366
333
-
En caso de que ya hayas recuperado el modelo del parent y quieres cargar una de sus relaciones, puedes usar el método `load(on:)` para hacerlo. Esto recuperará el modelo conectado de la base de datos y permitirá acceder a él como una propiedad local.
367
+
En caso de que ya hayas recuperado el modelo del parent y quieres cargar una de sus relaciones, puedes usar el método `get(reload:on:)` para hacerlo. Esto recuperará el modelo conectado de la base de datos (o de la caché, si está disponible) y permitirá acceder a él como una propiedad local.
334
368
335
369
```swift
336
-
planet.$star.load(on: database).map {
370
+
planet.$star.get(on: database).map {
337
371
print(planet.star.name)
338
372
}
339
373
340
374
// O
341
375
342
-
tryawait planet.$star.load(on: database)
376
+
tryawait planet.$star.get(on: database)
377
+
print(planet.star.name)
378
+
```
379
+
380
+
En caso de que quieras asegurarte de que los datos que recibes no se obtienen desde la caché, utiliza el parámetro `reload:`.
381
+
382
+
```swift
383
+
tryawait planet.$star.get(reload: true, on: database)
Copy file name to clipboardexpand all lines: docs/install/linux.es.md
+26-13
Original file line number
Diff line number
Diff line change
@@ -1,25 +1,38 @@
1
1
# Instalación en Linux
2
2
3
-
Para usar Vapor, necesitas Swift 5.9 o superior. Se puede instalar usando las opciones disponibles en [Swift.org](https://swift.org/download/).
3
+
Para usar Vapor, necesitas Swift 5.9 o superior. Esto se puede instalar utilizando la herramienta CLI [Swiftly](https://swiftlang.github.io/swiftly/) proporcionada por el Swift Server Workgroup (recomendado), o las toolchains disponibles en [Swift.org](https://swift.org/download/).
4
4
5
5
## Distribuciones y Versiones Soportadas
6
6
7
-
Vapor admite las mismas versiones de distribución de Linux que adminte Swift 5.9 o versiones más recientes.
8
-
9
-
!!! nota
10
-
Las versiones soportadas que se enumeran a continuación pueden quedar obsoletas en cualquier momento. Puedes comprobar qué sistemas operativos son oficialmente compatibles en la página [Swift Releases](https://swift.org/download/#releases).
11
-
12
-
|Distribución|Versión|Versión de Swift|
13
-
|-|-|-|
14
-
|Ubuntu|20.04|>= 5.9|
15
-
|Fedora|>= 30|>= 5.9|
16
-
|CentOS|8|>= 5.9|
17
-
|Amazon Linux|2|>= 5.9|
7
+
Vapor es compatible con las mismas versiones de distribuciones de Linux que soportan Swift 5.9 o versiones posteriores. Por favor, consulta la [página oficial de soporte](https://www.swift.org/platform-support/) para obtener información actualizada sobre los sistemas operativos oficialmente compatibles.
18
8
19
9
Las distribuciones de Linux que no son oficialmente compatibles también pueden ejecutar Swift al compilar el código fuente, pero Vapor no puede garantizar estabilidad. Puedes aprender más sobre cómo compilar Swift desde [Swift Repo](https://github.com/apple/swift#getting-started).
20
10
21
11
## Instalar Swift
22
12
13
+
### Instalación automatizada usando la herramienta Swiftly CLI (recomendada)
14
+
15
+
Visita el [sitio web de Swiftly](https://swiftlang.github.io/swiftly/) para obtener instrucciones sobre cómo instalar Swiftly y Swift en Linux. Después de eso, instala Swift con el siguiente comando:
16
+
17
+
#### Uso básico
18
+
19
+
```sh
20
+
$ swiftly install latest
21
+
22
+
Fetching the latest stable Swift release...
23
+
Installing Swift 5.9.1
24
+
Downloaded 488.5 MiB of 488.5 MiB
25
+
Extracting toolchain...
26
+
Swift 5.9.1 installed successfully!
27
+
28
+
$ swift --version
29
+
30
+
Swift version 5.9.1 (swift-5.9.1-RELEASE)
31
+
Target: x86_64-unknown-linux-gnu
32
+
```
33
+
34
+
### Instalación manual con la toolchain
35
+
23
36
Visita la guía [Using Downloads](https://swift.org/download/#using-downloads) de Swift.org para ver las instrucciones de cómo instalar Swift en Linux.
24
37
25
38
### Fedora
@@ -30,7 +43,7 @@ Los usuarios de Fedora pueden simplemente utilizar el siguiente comando para ins
30
43
sudo dnf install swift-lang
31
44
```
32
45
33
-
Si utilizas Fedora 30, deberás agregar EPEL 8 para obtener Swift 5.9 o versiones más nuevas.
46
+
Si utilizas Fedora 35, deberás agregar EPEL 8 para obtener Swift 5.9 o versiones más nuevas.
Copy file name to clipboardexpand all lines: docs/leaf/overview.es.md
+6
Original file line number
Diff line number
Diff line change
@@ -264,6 +264,12 @@ Puede pasar una cadena de formateado de fecha personalizada como segundo argumen
264
264
The date is #date(now, "yyyy-MM-dd")
265
265
```
266
266
267
+
También puedes pasar un ID de zona horaria para el formateador de fechas como tercer argumento. Consulta la documentación de Swift sobre [`DateFormatter.timeZone`](https://developer.apple.com/documentation/foundation/dateformatter/1411406-timezone) y [`TimeZone`](https://developer.apple.com/documentation/foundation/timezone) para más información.
268
+
269
+
```leaf
270
+
The date is #date(now, "yyyy-MM-dd", "America/New_York")
271
+
```
272
+
267
273
#### `#unsafeHTML`
268
274
269
275
La etiqueta `#unsafeHTML` actúa como una etiqueta variable - p. ej. `#(variable)`. Sin embargo, no escapa ningún HTML que `variable` pueda contener:
0 commit comments