Introducción

1

Qué necesitas para este curso y qué aprenderás sobre Node.js con Hapi

2

Conceptos principales de hapi y creación de nuestro primer servidor

3

Breve historia y estado actual

Creando un sitio básico con Hapi

4

El objeto h, response y sus herramientas

5

Uso de plugins - Contenido estático

6

Plantillas con Handlebars

7

Renderizado de vistas - Layout y template del home

8

Recibiendo parámetros en una ruta POST - Creación del registro

9

Definir una mejor estructura con buenas prácticas en Hapi

10

Validando la información - Implementando Joi

11

Introducción a Firebase

12

Creando un modelo y guardando en firebase

13

Implementando el login y validación del usuario

14

Autenticación de usuarios - Cookies y estado

15

Manejando errores

16

Visualización de errores

17

Controlar el error 404 en inert y el error de validación

18

Repaso - Creación del modelo y controlador para preguntas

19

Repaso - Creación de las rutas para crear preguntas

20

Listar las últimas preguntas en el home

Aplicacion de conceptos avanzados

21

Enrutamiento avanzado - visualizando una pregunta

22

Enrutamiento avanzado - respondiendo una pregunta

23

Generando la lógica de la plantilla según si es creador o contribuidor

24

Métodos de servidor - respuesta correcta

25

Usando métodos de servidor

26

Manejo del caché - Agregando el home al caché

27

Procesamiento de archivos - Aceptando imágenes

28

Logging con Good - Monitoreando el servidor

29

Creación de plugins - Teoría

30

Creación de plugins - Implementando un API REST

31

Estrategías de autenticación - Asegurando el API REST

32

Seguridad básica - Asegurando el servidor contra CSRF

33

Seguridad básica - Asegurando el servidor contra XSS

Herramientas de desarrollo

34

Depuración del proyecto

35

Ecosistema de Hapi

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Última oportunidad para asegurar tu aprendizaje por 1 año a precio especial

Antes: $249

Currency
$189/año

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

0D
7H
23M
33S

Enrutamiento avanzado - respondiendo una pregunta

22/35
Recursos

Para crear la funcionalidad de respuesta, creamos un método nuevo en el modelo de preguntas llamado answer. Este método nos permitirá insertar con push el objeto con la respuesta individual para una pregunta que será almacenada en un arreglo child llamado answers.

Luego definimos el método respectivo en el controlador de las preguntas y creamos la ruta que manejará el envío de las respuestas desde el formulario.

Es importante tener en cuenta que el ID de la pregunta que estamos respondiendo, corresponde a un input de tipo hidden en la vista, por lo que debemos asignar apropiadamente su valor a partir del key recibido en la ruta.

Finalmente, actualizamos la vista de detalles de pregunta, recordando que las respuestas son un arreglo en la base de datos de Firebase, por lo que deberemos recorrerlo igualmente con la instrucción {#each ... } ... {/each} de handlebars.

Para el conteo de las respuestas crearemos un helper personalizado de handlebars y lo registraremos en el index.js con el método .registerHelper( ‘<nombre helper>’, <función helper> ). Los helpers son funciones de JavaScript que están disponibles globalmente en la aplicación para ser incluídas en cualquiera de las vistas.

Aportes 12

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

En el helper del conteo, pudiéramos validar si el arreglo de respuestas viene en null para devolver 0, y así no tendríamos que incluir el tag #if en la plantilla.

no sería mejor crear un modelo para “answer” ?

Para evitar el if dentro del archivo index.hbs podemos poner el siguiente código en el index.js

handlerbars.registerHelper('answerNumber', (answers) => {
  if (!answers) return 0;
  const keys = Object.keys(answers).length;
  return keys;
});

en el archivo index.hbs solo agregamos esto

{{answerNumber question.answers}}

😊✌

A la funcion answerQuestion agregué un if() que evalúa si el usuario está o no está logueado. Si no lo esta, lo redirecciona al login.

async function answerQuestion (req, h) {
  if (!req.state.user) {
    return h.redirect('/login')
  }
  let result
  try {
    result = await questions.answer(req.payload, req.state.user)
    console.log('Respuesta creada' + result);
  } catch (error) {
    console.error(error);
  }

  return h.redirect('/question/' + req.payload.id)
}```

Me sigue gustando más como se ve con pug…
El punto es que pug acepta bloques de código dentro de la vista

extends ./layout/layout

block content
  main.container-fluid(role="main")
    .jumbotron.bg-white
      .container
        h1.display-3 FAQ
        p
          | The best place to learn and for those who are learning, ask a question
          | to clarify your doubts and share your knowledge if you know the answer

    .container
      h2.mb-4 Last Questions
      if questions 
        each q, key in questions
          .card.bg-white.mb-3
            .card-body
              .row
                .col-2.text-center
                  a.text-dark(href="#")
                    -
                      let numAns = 0;
                      if(q.answers){
                       numAns = Object.keys(q.answers).length
                      }
                    h3=numAns
                    | Answers
                .col-10.d-flex.align-items-stretch
                  h4.mt-3
                    a.text-dark(href="/question/"+key)= q.title
          hr
      else 
        .card.bg-white.mb-3
          .card-body
            .row
              .col-2.text-center
                h3 
              .col-10.d-flex.align-items-stretch
                h4.mt-3= error

block footer
  include ./partials/footer
block scripts
  include ./partials/scripts

controller.question.js

'use strict'

const questions = require('../models/index').questions

async function createQuestion(req, h) {
    let result

    try {
        result = await questions.create(req.payload, req.state.user)
        console.log(`Pregunta creada con el ID: ${result}`)
        return h.response(`Pregunta creada con el ID: ${result}`)
    } catch (error) {
        console.error(`Ocurrio un error: ${error}`)

        return h.view('ask', {
            title: 'Crear pregunta',
            error: 'Problemas creado la pregunta'
        }).code(500).takeover()
    }
}

async function answerQuestion(req, h) {
    let result
    try {
        result = questions.answer(req.payload, req.state.user)
        console.log(`Respuesta creada: ${result}`)
    } catch (error) {
        console.error(error)
    }

    return h.redirect(`/question/${req.payload.id}`)
}

module.exports = {
    createQuestion: createQuestion,
    answerQuestion: answerQuestion
}

models.questions.js

'use strict'

class Quiestions {
    constructor(db) {
        this.db = db
        this.ref = this.db.ref('/')
        this.collection = this.ref.child('questions')
    }

    async create (data, user) {
        const ask = {
            ...data
        }
        ask.owner = user
        const question = this.collection.push()
        question.set(ask)

        return question.key
    }

    async getLast(amount) {
        const query = await this.collection.limitToLast(amount).once('value')
        const data = query.val()
        return data
    }

    async getOne (id) {
        const query = await this.collection.child(id).once('value')
        const data = query.val()
        return data
    }

    async answer (data, user) {
        const answers = await this.collection.child(data.id).child('answers').push()
        answers.set({
            text: data.answer, 
            user: user
        })
        return answers
    }
}

module.exports = Quiestions

no es malo tener el id en el input vacio , ya que se puede ver en inspeccionar > elementos ?, o si hay ?

Modifique un poco el código y quedo así:
index.js

handlebars.registerHelper('answerNumber', (answers) => {
  if (answers === undefined) {
    return 0;
  }
  const keys = Object.keys(answers);
  return keys.length;
});

index.hbs

<h3>
  {{answerNumber question.answers}}
</h3>

me agrado la funcion que tiene handlerbars, me gustaria aplicar esa parte con express js

En el modelo de questions, en la funcion getOne, pueden modificar data.answers para que quede ordenado, siguiendo el ejemplo de un compañero de la clase anterior quedaría así.

  async getOne(id){
    const query = await this.collection.child(id).once('value');
    const data = query.val();
    const orderedAnswers = {};
    Object.keys(data.answers).reverse().map(key => orderedAnswers[key] = data.answers[key]);
    return {
      ...data,
      answers: orderedAnswers,
    };
  }```