You are viewing the Spanish (Mexico) site, but your language preference is set to English. Switch to English site →

Menu

Expand
Calificar esta página:

Recordatorios de citas con Ruby y Rails

¡Ahoy! Ahora te recomendamos que crees tus recordatorios de citas SMS con la funcionalidad de programación de mensajes integrada de Twilio. Dirígete a la Documentación de recursos de mensajes para obtener más información sobre la programación de mensajes de SMS.

¿Estás listo para implementar recordatorios de citas en tu aplicación móvil? Así es como funciona a un nivel alto:

  1. Un administrador crea una cita para una fecha y hora futuras y almacena el número de teléfono de un cliente en la base de datos de esa cita
  2. Un proceso en segundo plano comprueba la base de datos a intervalos regulares y busca citas que requieran el envío de un recordatorio
  3. A una hora configurada antes de la cita, se envía un recordatorio por SMS al cliente para recordarle su cita

Componentes básicos

Estas son las tecnologías que utilizaremos para conseguir esto:

  • Ruby on Rails para crear una aplicación web basada en bases de datos
  • El recurso mensajes de la API REST de Twilio para enviar mensajes de texto
  • Delayed::Job para ayudarnos a programar y ejecutar tareas en segundo plano de forma recurrente

Cómo leer este tutorial

Para implementar los recordatorios de citas, trabajaremos en una serie de historias de usuarios que describen cómo implementar por completo los recordatorios de citas en una aplicación web. Analizaremos el código necesario para satisfacer cada historia y exploraremos lo que necesitábamos añadir en cada paso.

Todo esto se puede hacer con la ayuda de Twilio en menos de media hora.

¡Empecemos!

Creación de una cita

Como usuario, quiero crear una cita con un nombre, números de teléfono de invitado y una hora en el futuro.

Para crear una app de recordatorios de citas automatizada, probablemente deberíamos empezar con una cita. Esta historia requiere que creemos un poco de interfaz de usuario y un objeto de modelo para crear y guardar una Appointment nueva en nuestro sistema. A un nivel alto, esto es lo que necesitaremos añadir:

  • Un formulario para introducir detalles sobre la cita
  • Una función de ruta y controlador en el servidor para representar el formulario
  • Una función de ruta y controlador en el servidor para manejar la solicitud POST del formulario
  • Un objeto de modelo persistente de Appointment para almacenar información sobre el usuario

Empecemos por observar el modelo, en el que decidimos qué información queremos almacenar con la cita.

Consulta nuestro modelo de cita

El generador de Rails

Por lo general, en este punto del tutorial, crearíamos nuestro modelo, vista y controlador desde cero (consulta la verificación de cuentas como ejemplo). Pero dado que el modelo de cita es tan sencillo y, solo queremos la estructura CRUD básica, utilizaremos el generador de Rails por primera vez.

Una nota sobre las herramientas

En esta app utilizamos Rails 4, pero será muy similar al 3 y versiones anteriores. También usaremos la biblioteca auxiliar twilio-ruby. Por último, usamos bootstrap para simplificar el diseño, y en este caso hay una gema que generará vistas temáticas de bootstrap llamadas twitter-bootstrap-rails. Revisa estas herramientas cuando tengas una oportunidad, ahora pasemos a generar nuestra estructura.

Generar un modelo, una vista y un controlador

Rails generate es una herramienta de línea de comandos que genera componentes de Rails como modelos, vistas, pruebas y mucho más. Para nuestros propósitos vamos a utilizar el gran e importante generador, scaffold para generar todo a la vez.

Así es como lo hicimos. Desde nuestra app Rails, ejecutamos:

$ bin/rails generate scaffold Appointment name:string phone_number:string time:datetime

Esto le dice a nuestro generador que cree “scaffolding” (estructura) para un recurso llamado Appointment (Cita), que tiene las propiedades name, phone_number y time.

Ahora vamos al modelo que se generó y agregaremos algunas cosas.

Mejorar el modelo de cita

Modelo de cita

El modelo de cita es bastante simple, pero dado que los humanos interactuarán con él, asegurémonos de añadir validación de datos.

Validación de datos

Las validaciones son importantes, ya que queremos asegurarnos de que solo se guarden datos precisos en nuestra base de datos. En este caso, solo queremos validar que todos nuestros campos obligatorios están presentes. Podemos hacerlo creando una afirmación validates con presence: true.

Es probable que una persona admin cree nuestro modelo de cita en el lugar de la cita. Bueno, sería genial que pudiéramos dar a nuestro usuario admin algunos comentarios cuando creen la cita. Afortunadamente, si añadimos validaciones a nuestros modelos en Rails obtenemos informes de errores gratis con el objeto flash de la sesión.

Una nota: para ejecutar esta demostración necesitarás ejecutar rake db:migrate la cual ejecutaría las migraciones en nuestra carpeta db/migrate. Para este tutorial nos centraremos en los conceptos principales, pero si quieres obtener más información sobre migraciones puedes leer la Guía de Rails sobre el tema.

Loading Code Sample...
        
        
        app/models/appointment.rb

        Appointment Model

        app/models/appointment.rb

        Ahora estamos listos para pasar al nivel de controlador de la aplicación móvil, empezando por las rutas de solicitud HTTP que necesitaremos.

        Configurar algunas rutas

        Rutas

        En una aplicación de Rails, Resource Routing asigna de forma automática las capacidades CRUD de un recurso a su controlador. Como nuestra Appointment es un recurso ActiveRecord, podemos decirle a Rails que queremos utilizar estas rutas, lo que nos ahorrará algunas líneas de código.

        Esto significa que en esta única línea de código tenemos de forma automática una ruta appointment/new que representará nuestro archivo appointment/new.html.erb de forma automática.

        Loading Code Sample...
              
              
              config/routes.rb

              Routes

              config/routes.rb

              Echemos un vistazo a este formulario.

              Nuestro formulario de cita nuevo

              Formulario de cita nuevo

              Cuando creamos una cita nueva, necesitamos un nombre de invitado, un número de teléfono y una hora. Mediante el uso de la etiqueta form_for de Rails podemos vincular el formulario al objeto de modelo. Esto generará la marca de HTML necesaria que creará una cita nueva en el envío.

              Loading Code Sample...
                    
                    
                    app/views/appointments/_form.html.erb

                    Appointment Form

                    app/views/appointments/_form.html.erb

                    Señalemos una etiqueta auxiliar específica que Rails nos brinda para formularios vinculados a modelos.

                    Una y otra vez

                    Fecha y hora

                    Una posible pérdida de tiempo es averiguar cómo gestionar la fecha y hora de la cita. En realidad, se trata de dos entradas de usuario independientes, una para el día y otra para la hora de la cita. Necesitamos una manera de combinar estas dos entradas separadas en un parámetro en el lado del servidor. Rails gestiona esto de nuevo dándonos las etiquetas data_select y time_select que el servidor reúne de forma automática en un parámetro que se asigna a la propiedad appointment.time.

                    Loading Code Sample...
                          
                          
                          app/views/appointments/_form.html.erb

                          Entradas de fecha y hora

                          app/views/appointments/_form.html.erb

                          Volvamos al controlador para ver qué sucede cuando creamos esta cita.

                          Gestor de creación de citas

                          Gestionar el formulario POST

                          Uno de los otros controladores prácticos creados por nuestra ruta de recursos Appointment era appointment/create que gestiona POST desde nuestro formulario.

                          En nuestro controlador tomamos la entrada de nuestro formulario y creamos un modelo Appointment nuevo. Si la cita se guarda con éxito en la base de datos, redirigiremos a la vista de detalles de la cita, que mostrará al creador la cita nueva y le permitirá editarla o eliminarla.

                          Loading Code Sample...
                                
                                
                                app/controllers/appointments_controller.rb

                                Gestionar el formulario POST, crear una cita

                                app/controllers/appointments_controller.rb

                                A continuación, echaremos un vistazo a los controladores generados para editar y eliminar.

                                Interactuar con citas

                                Interactuar con citas

                                Como usuario, deseo ver una lista de todas las citas futuras y poder eliminarlas.

                                Si eres una organización que gestiona muchas citas, es probable desees poder verlas y gestionarlas en una única interfaz. Eso es lo que abordaremos en esta historia de usuario. Crearemos una interfaz de usuario para:

                                • Mostrar todas las citas
                                • Eliminar las citas individuales

                                Empecemos por mirar el controlador.

                                Mostrar una lista de citas

                                Mostrar una lista de citas

                                En el nivel de controlador, todo lo que haremos es obtener una lista de todas las citas en la base de datos y las representaremos con una vista. También debemos añadir un aviso si no hay ninguna cita, ya que esta demostración depende de que haya al menos una cita en el futuro.

                                Loading Code Sample...
                                      
                                      
                                      app/controllers/appointments_controller.rb

                                      Mostrar una lista de citas

                                      app/controllers/appointments_controller.rb

                                      Volvamos a la plantilla para ver nuestra lista de citas.

                                      Ver todas las citas

                                      Ver todas las citas

                                      La vista de índice muestra todas las citas, que se ordenan de forma automática por date_created. Lo único que necesitamos añadir para completar nuestra historia de usuario es un botón de eliminación. Añadiremos el botón de edición solo por diversión.

                                      Helpers de URL

                                      Puedes notar que en lugar de codificar las URL para editar y eliminar estamos usando un Helper de URL de Rails. Si ves la marca representada, verás estas rutas:

                                      • /appointments/ID/edit para editar
                                      • /appointments/ID para eliminar, con un método HTTP DELETE anexado a la consulta

                                      Estos helpers de URL pueden tomar un objeto de cita o un ID.

                                      Existen otros helpers en este código que Rails genera por nosotros. Lo que quiero señalar es la etiqueta :confirm. La etiqueta confirm (confirmar) es un atributo de datos que interrumpe la solicitud DELETE real con una alerta de javascript. Estas son las prácticas recomendadas para llamar a DELETE en un objeto. Si el usuario confirma que procesamos la solicitud con normalidad, de lo contrario no se realizará ninguna acción.

                                      Loading Code Sample...
                                            
                                            
                                            app/views/appointments/index.html.erb

                                            View All Appointments

                                            app/views/appointments/index.html.erb

                                            Ahora veamos lo que sucede en el controlador cuando pedimos que se elimine una cita.

                                            Buscar una cita

                                            Buscar una cita

                                            En este controlador necesitamos extraer un registro de cita y, a continuación, eliminarlo. Echemos un vistazo a cómo obtenemos la cita en primer lugar.

                                            Puesto que es probable que necesitaremos un registro de cita en la mayoría de nuestras vistas, deberíamos crear un método de instancia privada que se pueda compartir entre varios controladores.

                                            En set_appointment utilizamos el parámetro de ID, que se transfiere desde la ruta, para buscar la cita. Luego en la parte superior de nuestro controlador usamos el filtro before_action de la siguiente manera:

                                            before_action :set_appointment, only: [:show, :edit, :update, :destroy]
                                            

                                            Esto indica a nuestra aplicación móvil a qué controladores aplicar este filtro. En este caso, solo necesitamos una cita cuando el controlador se ocupa de una sola cita.

                                            Loading Code Sample...
                                                  
                                                  
                                                  app/controllers/appointments_controller.rb

                                                  Buscar una cita

                                                  app/controllers/appointments_controller.rb

                                                  Ahora veamos lo que sucede cuando se elimina una cita.

                                                  Eliminar una cita

                                                  Eliminar una cita

                                                  Ahora que tenemos la cita, solo tenemos que llamar a .destroy. En una app de producción que te recomendamos evaluar si debes utilizar .delete en lugar de destruir, ya que ambas son formas válidas de eliminar una fila de la base de datos en Rails. Para nuestros propósitos utilizaremos la destrucción menos eficaz por dos razones:

                                                  1. Gestiona la limpieza de la base de datos
                                                  2. Mantiene la Appointment en la memoria, de modo que podamos enviar un mensaje de éxito al usuario
                                                  Loading Code Sample...
                                                        
                                                        
                                                        app/controllers/appointments_controller.rb

                                                        Eliminar una cita

                                                        app/controllers/appointments_controller.rb

                                                        Ahora que podemos interactuar con nuestras citas, vamos a dedicarnos al envío de recordatorios cuando se acerca una de estas citas.

                                                        Enviar el recordatorio

                                                        Enviar el recordatorio

                                                        Como un sistema de citas, deseo notificar a un usuario mediante SMS en un intervalo arbitrario antes de una cita futura.

                                                        Existen muchas formas de crear esta parte de nuestra aplicación, pero no importa cómo la implementes, debe haber dos partes móviles:

                                                        • Una secuencia de comandos que comprueba la base de datos para cualquier cita próxima y, a continuación, envía un SMS
                                                        • Un trabajador que ejecuta esa secuencia de forma continua
                                                        Loading Code Sample...
                                                              
                                                              
                                                              app/models/appointment.rb

                                                              Enviar el recordatorio

                                                              app/models/appointment.rb

                                                              Echemos un vistazo a cómo decidimos implementar este último con Delayed::Job.

                                                              Trabajar con Delayed::Job

                                                              Trabajar con Delayed::Job

                                                              Como mencionamos antes, hay muchas maneras de implementar un planificador o trabajador, pero en Rails Delayed::Job es el más establecido.

                                                              Delayed Job necesita una actividad en segundo plano de algún tipo para poner en cola los trabajos siguientes. Aquí hemos añadido el adaptador ActiveRecord para delayed_job, que utiliza nuestra base de datos a fin de almacenar la base de datos de 'Jobs'. Hay bastantes actividades en segundo plano soportadas, así que usa la gema correcta para tu aplicación móvil.

                                                              Una vez incluida la gema, necesitamos ejecutar bundle install y ejecutar la tarea de Rake para crear la base de datos.

                                                              rails g delayed_job:active_record

                                                              Puedes ver todos estos pasos en el repositorio de Github para este proyecto.

                                                              Loading Code Sample...
                                                                    
                                                                    
                                                                    The Rails Generator

                                                                    Gemfile for Appointment Reminders

                                                                    The Rails Generator

                                                                    Ahora estamos listos para crear el trabajo real.

                                                                    Enviar un recordatorio

                                                                    Enviar un recordatorio

                                                                    El siguiente paso para enviar un recordatorio a nuestro usuario es crear la secuencia de comandos que se activará en algún intervalo antes de la hora de la cita. Terminaremos deseando programar este recordatorio cuando se cree la cita, por lo que tiene sentido escribirlo como método en el modelo de cita.

                                                                    Lo primero que hacemos es crear un Twilio Client que enviará nuestros SMS mediante la API REST de Twilio. Necesitaremos tres cosas para crear el Twilio Client:

                                                                    • Nuestro SID de cuenta de Twilio
                                                                    • Nuestro token de autenticación Twilio
                                                                    • Un número de Twilio en nuestra cuenta que pueda enviar mensajes de texto

                                                                    Todos estos elementos se encuentran en la consola.

                                                                    Entonces lo que tenemos que hacer para enviar un SMS es utilizar messages.create() incorporado a fin de enviar un SMS al teléfono del usuario.

                                                                    Devolución de llamada de modelo

                                                                    Como hicimos nuestra secuencia de comandos de recordatorio un método en el modelo, obtenemos una herramienta muy útil; una devolución de llamada. Cuando se usa la devolución de llamada before_create nos aseguramos de que se llame al recordatorio siempre que se cree una cita.

                                                                    Loading Code Sample...
                                                                          
                                                                          
                                                                          app/models/appointment.rb

                                                                          Enviar un recordatorio

                                                                          app/models/appointment.rb

                                                                          El último paso es asegurarse de que Delayed Job siempre termine programando esta devolución de llamada.

                                                                          Programar un recordatorio

                                                                          Programar un recordatorio

                                                                          Bueno, ya casi hemos terminado, ahora lo que tenemos que hacer es escribir un controlador de horarios extremadamente complicado que haga lo siguiente:

                                                                          • Buscar cada cita futura
                                                                          • Añadirla a una tabla de Jobs
                                                                          • Comprobar si se encuentra dentro del intervalo minutes_before_appointment
                                                                          • Activar el método de recordatorio

                                                                          Espera, Delayed Job hace esto de forma gratuita en un método práctico llamado handle_asynchronously que le indica a Delayed Job que programe este trabajo siempre que se active este método. Puesto que nuestro tiempo de trabajo depende de la instance de la cita individual, necesitamos transferir una función al método handle_asynchronously que calculará el tiempo. En este caso, minutes_before_appointment se establece en 30 minutos, pero puedes utilizar cualquier intervalo de Time aquí.

                                                                          Ahora, cuando creemos una cita, veremos una fila nueva en la tabla de Jobs, con una hora y un método que se deben activar. Además, delayed_job guarda los errores e intentos para que podamos depurar cualquier rareza antes de que falle. Una vez que activa un trabajo, lo elimina de la base de datos, por lo que en un buen día deberíamos ver una base de datos vacía.

                                                                          Loading Code Sample...
                                                                                
                                                                                
                                                                                app/models/appointment.rb

                                                                                Programar un recordatorio

                                                                                app/models/appointment.rb

                                                                                Todo listo

                                                                                Increíble, eso fue todo un trabajo, pero en realidad tuvimos que escribir muy poco código para obtener recordatorios de citas automáticos activados con Twilio.

                                                                                ¿Dónde ir a continuación?

                                                                                ¿Dónde ir a continuación?

                                                                                Con un poco de código y una pizca de configuración, estamos listos para recibir recordatorios de citas automatizados en nuestra aplicación móvil. ¡Bien hecho!

                                                                                Si eres un desarrollador de Ruby que trabaja con Twilio, puedes consultar otros tutoriales en Ruby:

                                                                                Clic para llamar

                                                                                Coloca un botón en tu página web que conecte a los visitantes con el servicio de asistencia en directo o con el personal de ventas por teléfono.

                                                                                Autenticación de dos factores

                                                                                Mejora la seguridad de la funcionalidad de inicio de sesión de la app Ruby al añadir autenticación de dos factores por mensajes de texto.

                                                                                ¿Te ayudó esto?

                                                                                Gracias por consultar este tutorial. Si tienes algún comentario que compartir con nosotros, comunícate con nosotros en Twitter... nos encantaría saber lo que piensas y conocer lo que estás creando.

                                                                                Jarod Reyes Kevin Segovia Daniel Erazo
                                                                                Calificar esta página:

                                                                                ¿Necesitas ayuda?

                                                                                Todos la necesitamos a veces; la programación es difícil. Obtén ayuda ahora de nuestro equipo de soporte, o recurre a la sabiduría de la multitud visitando Stack Overflow Collective de Twilio o navegando por la etiqueta de Twilio en Stack Overflow.

                                                                                Loading Code Sample...
                                                                                      
                                                                                      
                                                                                      

                                                                                      Gracias por tus comentarios.

                                                                                      Selecciona los motivos de tus comentarios. La información adicional que nos brindas nos ayuda a mejorar nuestra documentación:

                                                                                      Enviando tus comentarios…
                                                                                      🎉 Gracias por tus comentarios.
                                                                                      Se produjo un error. Inténtalo de nuevo.

                                                                                      Gracias por tus comentarios.

                                                                                      thanks-feedback-gif