Haciendo el blog dinámico
La segunda parte del video tutorial continúa aquí:
Aviso de contenido obsoleto
Estos videos fueron grabados con una versión anterior de Redwood y muchos comandos están desactualizados. Si quiere construir el blog necesitará acompañar el vídeo con este texto, que está actualizado a la última versión.
Tener una página de inicio y una "acerca de" está muy bien pero, ¿dónde están los artículos del blog? A continuación vamos a trabajar en ellos.
Para nuestro tutorial vamos a cargar las entradas (artículos o Posts) desde la base de datos. Dado que las bases de datos relacionales siguen siendo fundamentales de muchas aplicaciones web complejas (y no tan complejas), en Redwood hemos hecho que el acceso SQL sea de primera. Todo empieza con un esquema.
#
Creando el esquema de base de datosTenemos que decidir qué datos necesita para una entrada del blog, de ahora en más nos referiremos a Post. Para empezar podemos definir:
id
el identificador de cada Post (toda tabla de base de datos debe tener una clave primaria)title (título)
body
el contenido del postcreatedAt
una marca de tiempo de cuando se creó el post
Usamos Prisma para conectarnos con la base de datos. Prisma tiene otra biblioteca llamada Migrate que permite actualizar el esquema de la base de datos de forma predecible y capturar cada uno de los cambios. Cada cambio se llama una migration y Migrate creará uno cuando hagamos cambios en nuestro esquema.
Primero definamos la estructura de datos para un post. Abra api/db/schema.prisma
y añada la definición de nuestra tabla Post (borre los modelos de "muestra" que estén presentes en el archivo, como el UserExample
). Una vez que haya terminado el archivo completo debería ser así:
Esto dice que queremos una tabla llamada Post
con las siguientes columnas:
- Una columna
id
de tipoInt
(entero), le indica a Prisma que debe usarla como identificador@id
(para asociarse con otras tablas) y que el valor por omisión@default
debe ser el métodoautoincrement()
provisto por Prisma que indica la base de datos debe autogenerarlo al crear un nuevo registro - Una columna "título"
title
que contendrá una "cadena de caracteres"String
- Una columna para el contenido
body
también tipoString
- Una columna
createdAt
de tipoDateTime
y@default
que tome el tiempo actualnow()
al crear el registro (lo que nos evita hacerlo manualmente en la aplicación)
Identificadores Int o String
Para este tutorial mantendremos las cosas simples usando un entero como ID. Las aplicaciones pueden usar otros tipos soportados por Prisma como CUID o UUID. En cuyo caso sería
String
en lugar deInt
y se usaríacuid()
ouuid()
en lugar deautoincrement()
:
id String @id @default(cuid())
Los Ints simplifican las URLs por ejemplo https://redwoodblog.com/posts/123 en lugar de https://redwoodblog.com/posts/eebb026c-b661-42fe-93bf-f1a373421a13.
Para más información sobre IDs vea la documentación oficial de Prisma.
#
MigracionesEso fue sencillo. Ahora querremos capturar ese cambio como una migración:
Atajo
redwood
A partir de ahora usamos el alias
rw
en lugar deredwood
por brevedad.
Se le pedirá darle un nombre a esta migración. Algo que describa lo que hace, por ejemplo "cómo crear posts" (sin comillas). Esto es para su propio beneficio—a Redwood no le importa el nombre de la migración, es sólo una referencia al buscar viejas migraciones y facilita encontrar cuando creó o modificó algo específico.
Cuando termine el comando, verá un nuevo subdirectorio dentro de api/db/migrations
que tiene una marca de tiempo y el nombre de la migración. Contendrá un único archivo migration.sql
con el SQL necesario para actualizar la estructura de base de datos con la versión de schema.prisma
que tenía en el momento en que se creó. Por lo que tendremos un schema.prisma
que describe la estructura de la base de datos actualmente y las migraciones tienen el historial de cambios antes de llegar al estado actual. Es una forma de hacer control de versiones para la estructura de base de datos, que puede ser bastante útil.
Además de crear el archivo de migración, el comando anterior también ejecutará SQL en base de datos, para "efectuar" la migración. Al final tendremos una nueva tabla en la base de datos llamada Post
con las columnas que definimos anteriormente.
#
Editor de postsTodavía no hemos decidido el aspecto de nuestro sitio, ¡no sería sorprendente si editáramos los posts sin escribir un montón de páginas que probablemente tiraremos una vez que el equipo de diseño las vea? ¡Por suerte, "Increíble" es el segundo nombre de Redwood! No tiene apellido.
Generemos pues lo que necesitamos para hacer operaciones de CRUD (crear, consultar, actualizar y borrar en inglés) en los Posts así podremos verificar las columnas de la base de datos, y además consultar algunos Posts de ejemplo para empezar a crear páginas y contenido real. Redwood tiene un comando para la ocasión:
Naveguemos a http://localhost:8910/posts
donde veremos:
Esto es poco más de lo que obtuvimos al generar una página. ¿Qué pasa si clicamos en el botón "New Post"?
Bien, por fin vamos a algún lado. Complete los campos y presione "Save".
¿Hemos creado un post en la base de datos? Y ahora vemos el post aquí en esta página? Sí, sí lo hicimos. Intente crear otro:
¿Qué pasa si clicamos "Editar" en uno de los Posts?
¿Y qué pasa si hacemos clic en "Borrar"?
Así que Redwood acaba de crear páginas, componentes y servicios necesarios para realizar todas las operaciones CRUD en nuestra tabla de Posts. No precisa abrir una herramienta GUI o iniciar sesión a través de una terminal y escribir SQL desde cero. Redwood llama a estos scaffolds (plantillas o andamios).
Esto es lo que pasó al ejecutar el comando yarn rw g scaffold post
:
- Se añadió un archivo SDL con consultas y mutaciones GraphQL:
api/src/graphql/posts.sdl.js
- Se añadió un archivo services en
api/src/services/posts/posts.js
con un cliente Prisma para leer y escribir datos en la base de datos - Se crearon varias pages en
web/src/pages
:EditPostPage
para modificarNewPostPage
para crear uno nuevoPostPage
para mostrar detallesPostsPage
para listar todos los posts
- Se creó una plantilla layout en
web/src/layouts/PostsLayout/PostsLayout.js
que contiene las páginas con elementos comunes como el encabezado y el botón de nuevos Posts "New Posts" - Se crearon rutas en forma de
Set
dentro la plantillaPostsLayout
para dichas páginas dentro deweb/src/Routes.js
- Se crearon tres células en
web/src/components
:EditPostCell
trae el post para editar desde la base de datosPostCell
muestra el postPostsCell
trae todos los posts
- Se crearon componentes en
web/src/components
:NewPost
muestra el formulario para crear un postPost
muestra un postPostForm
contiene el form usado por los componentes "New" y "Edit"Posts
muestra una tabla con todos los posts
Convenciones de nomenclatura
Notará que algunas de las partes generadas usan plural y otras singular. Esta convención está tomada de Ruby on Rails que usa una convención "humana": si se trata de múltiples instancias de algo (como la lista de los Posts) usará plural. Si trata con algo único (como crear un post) usará singular. También vuelve natural el hablar: "muéstreme una lista de todos los Posts" o "voy a crear un nuevo Post"
En lo que respecta a los generadores:
- Los servicios van siempre en plural.
- Los métodos del servicio son singulares o plural dependiendo de lo que devuelvan: múltiples Posts o solo uno (
posts
vs.createPost
).- Los archivos SDL usan plural.
- Las "pages" que vienen con los "scaffolds" son plurales o singulares según si se ocupan de muchos posts o de uno solo. El generador de
page
usará el nombre que le dé por argumento al comando.- Los "layouts" también usan el nombre del argumento del comando.
- Componentes y células, serán plurales o singulares dependiendo del contexto usado por el generador "scaffold", o bien usarán el argumento del comando.
Tenga en cuenta que el nombre de la tabla de base de datos determina el singular o plural, no toda la palabra. Por ejemplo
PostsCell
, en lugar dePostCells
.No tienes que seguir esta convención cuando cree sus propias partes, pero le recomendamos que lo haga. La comunidad de Ruby on Rails ama esta nomenclatura pese a que mucha gente se quejó de cuando se usó por primera vez. Dele cinco minutos.
#
Crear una página de inicioPodemos ir reemplazando estas páginas una por una a medida que tengamos diseños, o tal vez moverlos a la sección de administración de nuestro sitio y construir nuestras propias páginas de cero. El sitio público no permitirá a los visitantes crear, editar o eliminar posts. ¿Qué pueden hacer?
- Ver una lista de posts (sin enlaces para editar/eliminar)
- Ver un solo post
Puesto que de ahora en más querremos una forma de crear y editar posts, mantengamos las páginas generadas tal y como están y creemos nuevas páginas para esas dos acciones.
Ya tenemos HomePage
así que no necesitaremos crear eso. Para mostrar una lista de posts al visitante tendremos que añadir lógica. Necesitamos obtener el contenido de la base de datos y como no queremos que el usuario sólo vea una pantalla en blanco mientras lo hacemos (según condiciones de red, ubicación del servidor, etc), mostraremos un mensaje de cargando o una animación. Y si hay un error al traer los datos también deberemos manejarlo. ¿Y qué pasa cuando hacemos código libre el fuente de este blog y alguien lo pone en producción con la base de datos vacía? Sería bueno que hubiera algún tipo de mensaje en blanco.
Oh muchacho, nuestra primera página con datos y ya tenemos que preocuparnos por cargar estados, errores, páginas en blanco...o ¿no?