
Compartir:
Karl es un defensor de los desarrolladores para Vonage, centrado en el mantenimiento de nuestros SDK de servidor Ruby y la mejora de la experiencia de los desarrolladores para nuestra comunidad. Le encanta aprender, hacer cosas, compartir conocimientos y, en general, todo lo relacionado con la tecnología web.
Trabajar con variables de entorno en Ruby
Tiempo de lectura: 10 minutos
Cuando se trabaja con aplicaciones web, los desarrolladores tienen que manejar un montón de piezas móviles diferentes. La mayoría de las veces no nos paramos a pensar en cuáles son esas partes individuales y cómo funcionan exactamente. En este artículo, vamos a explorar sólo una de estas partes: las variables de entorno.
Si alguna vez has creado y desplegado una aplicación web en Ruby, probablemente hayas utilizado variables de entorno. Si esa aplicación fue construida con Ruby on Rails, entonces habrás necesitado configurar RAILS_ENV en 'production' durante el proceso de despliegue. Si la aplicación integraba servicios externos o APIs, entonces es probable que hayas utilizado variables de entorno para gestionar las credenciales de esos servicios.
Pero, ¿qué son exactamente son variables de entorno, por qué son útiles y cómo podemos aprovecharlas al desarrollar e implantar aplicaciones Ruby?
¿Qué son las variables de entorno?
Como su nombre indica, las variables de entorno son variables que almacenan información sobre el entorno en el que opera nuestra aplicación. Probablemente ya estés familiarizado con el concepto de variables y cómo funcionan, así que veamos un poco más de cerca esa segunda parte: entorno.
El entorno en este contexto puede referirse al sistema operativo en el que se ejecuta tu programa, pero también puede referirse al proceso, o procesos, utilizados para ejecutar el programa. Esto puede quedar un poco más claro si vemos algunos ejemplos.
Cuando abres una ventana Terminal en tu ordenador, se inicia un proceso Shell. Una Shell es esencialmente un programa que te permite interactuar con tu sistema procesando comandos emitidos a través de la Shell y mostrando el resultado. Por ejemplo, al arrancar una aplicación Rails en tu máquina local, emites un comando como rails s y veremos una salida como ésta:
=> Booting Puma
=> Rails 7.0.4.3 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 5.6.5 (ruby 3.0.0-p0) ("Birdie's Version")
* Min threads: 5
* Max threads: 5
* Environment: development
* PID: 126917
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
Este proceso, el Shell, sabe cosas sobre el entorno en el que se ejecuta, y almacena estas cosas que sabe en variables. Los procesos heredan una copia de las variables de entorno de su proceso padre, por lo que el Shell tiene una copia de las variables de entorno del sistema operativo (o más específicamente del kernel). Del mismo modo, cualquier proceso ejecutado en el Shell heredará una copia de las variables de entorno de ese Shell.
Acceso a las variables de entorno
En los sistemas basados en UNIX (por ejemplo, Linux y OSX) puede acceder a todas las variables de entorno del Shell utilizando el comando env . Windows tiene un comando set pero, para los propósitos de este artículo, sólo cubriremos los comandos utilizados en sistemas basados en UNIX.
Si desea imprimir una variable de entorno específica, puede utilizar el comando printenv comando. Por ejemplo, si quisiera comprobar el idioma que tengo configurado en mi sistema puedo emitir el comando printenv seguido del nombre de la variable de entorno que contiene este dato, en este caso LANG. Esto mostrará el idioma, que en mi sistema es en_GB.UTF-8:
$ printenv LANG
en_GB.UTF-8Un ejemplo más centrado en Ruby sería RUBY_VERSION:
$ printenv RUBY_VERSION
ruby-3.2.2Si fueras a ejecutar un proceso Ruby desde tu Shell, esta es la versión de Ruby que el proceso usaría. Si tienes instalado un gestor de versiones de Ruby, como chruby, rbenvo rvmpruebe a ejecutar printenv RUBY_VERSION luego cambia tu versión de Ruby con tu gestor de versiones y ejecuta printenv RUBY_VERSION de nuevo. Deberías ver la versión de Ruby que acabas de cambiar.
Hablando de procesos Ruby, podemos acceder a variables de entorno desde dentro de un programa Ruby mediante el objeto ENV de Ruby. Como indica la documentación de Ruby explica:
ENVes un accesorio tipo hash para variables de entorno.
La clase ENV tiene varios métodos diferentes que le permiten interactuar con los valores almacenados dentro de un objeto ENV objeto. Para los propósitos de este artículo, sólo estamos interesados en acceder a los valores utilizando la notación de corchetes, pero siéntete libre de explorar el resto de la funcionalidad descrita en la documentación de Documentación de Ruby.
Podemos acceder al valor de una variable de entorno a través de ENV mediante la notación de corchetes, del mismo modo que accederíamos a los valores de un Hash de Ruby, utilizando el nombre de la variable de entorno como clave.
ENV['RUBY_VERSION'] # => ruby-3.2.2
Tenga en cuenta que pasar el nombre de la variable RUBY_VERSIONcomo cadena a los ENV corchetes.
Vamos a probarlo en nuestro Shell:
$ printenv RUBY_VERSION
ruby-3.2.2
$ ruby -e "puts ENV['RUBY_VERSION']"
ruby-3.2.2En el ejemplo anterior, primero utilizamos el comando printenv para obtener el valor de la variable de entorno RUBY_VERSION que es ruby-3.2.2. A continuación, invocamos el comando ruby con la opción -e opción . Esto le dice al intérprete de Ruby que no ejecute la cadena que luego le pasamos como código Ruby. Este código Ruby devuelve el valor asociado al objeto ENV del objeto RUBY_VERSION del objeto. Como podemos ver, el valor de 'RUBY_VERSION' dentro del proceso Ruby es el mismo que el valor de RUBY_VERSION dentro de su proceso Shell padre.
Configuración de variables de entorno
Hasta ahora sólo hemos explorado cómo acceder a las variables de entorno existentes. Sin embargo, se vuelven aún más útiles cuando empiezas a configurar las tuyas propias.
En un shell basado en UNIX, las variables de entorno pueden establecerse mediante el comando export combinado con la sintaxis de asignación:
$ export FOO=bar
$ printenv FOO
barAl igual que con las variables de entorno preexistentes, las que creas dentro de un proceso también son heredadas por cualquier proceso hijo. De nuevo, podemos probar esto dentro de un proceso Ruby.
$ export FOO=bar
$ printenv FOO
bar
$ ruby -e "puts ENV['FOO']"
barAlgo importante a tener en cuenta es que los procesos hermanos mantienen sus propias copias de las variables de entorno en lugar de compartirlas. Si abre una segunda ventana de Terminal y ejecuta printenv FOOno se mostrará nada.
De forma similar, las variables de entorno creadas dentro de un proceso mueren con ese proceso. Por ejemplo, si ejecutas export FOO=barcierra la ventana Terminal, luego abre una nueva ventana Terminal y ejecuta printenv FOOno sale nada.
¿Por qué utilizar variables de entorno?
Uno de los principales usos de las variables de entorno es establecer datos de configuración al desarrollar o desplegar una aplicación. Un ejemplo común de esto es la configuración de credenciales de API cuando se utiliza un servicio externo como las API de comunicaciones de Vonage.
Digamos, por ejemplo, que tiene un archivo Ruby llamado send_sms.rb. El código de este archivo envía un SMS a través de la SMS API de Vonage utilizando el kit de desarrollo de software Ruby de Vonage. Para autenticar tu solicitud a la API de SMS de Vonage, debes instanciar un objeto Vonage::Client con un objeto api_key y api_secret.
client = Vonage::Client.new(api_key: 'abc123', api_secret: 'ab1CDef2GhIjkLmn')
client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')Generalmente, no querrás codificar estas credenciales en tu código fuente de esta manera. Es probable que envíes ese código a un servicio de control de versiones como GitHub; incluso si el repositorio no es público, no es una buena idea exponer tus credenciales de API en tu historial de Git. Además, es muy posible que utilices credenciales de API diferentes en desarrollo que en producción (y posiblemente también en otros entornos, como staging o QA). Las variables de entorno pueden actualizarse entre despliegues sin tener que modificar el código fuente.
En el contexto de una aplicación Ruby, aquí es donde podemos aprovechar el objeto ENV de Ruby. Nuestro código send_sms.rb actualizado podría ser algo así:
client = Vonage::Client.new(api_key: ENV['VONAGE_API_KEY'], api_secret: ENV['VONAGE_API_SECRET'])
client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')A continuación, puede utilizar export para establecer VONAGE_API_KEY y VONAGE_API_SECRET como variables de entorno:
$ export VONAGE_API_KEY=abc123 VONAGE_API_SECRET=ab1CDef2GhIjkLmnCuando ejecute posteriormente el archivo send_sms.rb el objeto ENV en el proceso Ruby que ejecute el código tendrá acceso a las variables de entorno que establezcas.
$ ruby send_sms.rbComo nota al margen, si no pasas los parámetros api_key y api_secret a Vonage::Client.newcuando sea necesario, el SDK Ruby de Vonage buscará automáticamente en el objeto ENV en busca de variables de entorno denominadas VONAGE_API_KEY y VONAGE_API_SECRET. Siempre que tengas estas variables de entorno configuradas cuando utilices las API de Vonage que requieren una clave y un secreto de API para la autenticación, puedes instanciar el objeto Vonage::Client de la siguiente manera:
client = Vonage::Client.new¿Quieres ver esto en acción dentro de una aplicación Rails? Echa un vistazo a nuestro tutorial sobre cómo enviar SMS con Ruby on Rails usando variables de entorno para las credenciales de Vonage.
Cómo utilizar las variables de entorno
En los ejemplos anteriores, has utilizado export para establecer tus variables de entorno. Hacer esto cada vez que ejecutas un proceso Ruby en un nuevo Shell o entorno puede volverse un poco laborioso, especialmente si tienes un gran número de variables de entorno que establecer. Afortunadamente hay otras soluciones disponibles tanto para desarrollo como para producción.
En desarrollo
Una gran opción en desarrollo es la dotenv biblioteca. Se trata de un RubyGem que puedes incluir en tu Gemfile o instalarla localmente. Para usarla, necesitas crear un archivo .env en la raíz de tu proyecto Ruby. Dentro de ese archivo, defines las variables de entorno que requiere tu aplicación como pares clave-valor.
VONAGE_API_KEY=abc123
VONAGE_API_SECRET=ab1CDef2GhIjkLmnEn su aplicación Ruby, puede entonces require la gema y llamar al método load en la clase Dotenv clase. Esto carga todas las variables de entorno definidas en tu archivo .env en el objeto ENV para el proceso Ruby actual.
require 'dotenv'
Dotenv.load
client = Vonage::Client.new(api_key: ENV['VONAGE_API_KEY'], api_secret: ENV['VONAGE_API_SECRET'])
client.sms.send(from: 'Ruby', to: '447700900000', text: 'Hello world')También hay una dotenv-rails gema incluida como parte de la biblioteca, que es específica para su uso con aplicaciones Rails. El uso es ligeramente distinto al de la gema dotenv pero el concepto es el mismo.
La biblioteca tiene algunas otras funcionalidades, que no voy a cubrir aquí, pero se puede leer en la documentación.
Una última observación: tanto si se utiliza dotenv o dotenv-rails debe asegurarse siempre de añadir su archivo .env a .gitignore para que no sea registrado en tu repositorio Git.
Si está creando una aplicación Rails que necesita pruebas de webhooks, probablemente querrá utilizar ngrok junto con dotenv. Consulta nuestra Guía de configuración de Rails + ngrok para una guía completa.
En producción
Aunque, según la documentación puede utilizar dotenv en producciónotras herramientas y opciones son más adecuadas para gestionar variables de entorno en producción.
Herramientas de gestión de la configuración como Chef, Puppety Ansible son opciones potentes y completas. Estas herramientas son probablemente las más adecuadas para trabajar a escala, pero probablemente sean excesivas para proyectos más pequeños si todo lo que quieres hacer es configurar unas pocas variables de entorno.
Una solución de contenedorización como Docker proporciona una forma específica de manejar variables de entorno para datos sensibles como claves API.
Si utiliza un servicio como Render o Heroku para desplegar y alojar tus aplicaciones Ruby, generalmente puedes establecer tus variables de entorno como pares clave-valor dentro de la interfaz de usuario proporcionada por el servicio, ya sea para una sola aplicación o para un grupo de aplicaciones (ver la captura de pantalla de abajo). Algunas variables de entorno de uso común pueden incluso establecerse por ti; por ejemplo, Render establece automáticamente
RAILS_ENVenproductionpara aplicaciones Ruby.
Render Environment Variable form
Breve nota sobre las credenciales de Rails
Si está trabajando específicamente con Rails, una alternativa al uso de variables de entorno es utilizar Credenciales Railsaunque ese es un tema para otra entrada del blog.
Conclusión
Esto es todo por ahora. Espero que este artículo le haya resultado interesante e informativo.
Si estás listo para ver cómo las variables de entorno potencian una experiencia de mensajería real, echa un vistazo a este tutorial sobre el envío de respuestas sugeridas RCS con Ruby on Rails. Muestra cómo combinar la configuración del entorno, Rails y la API de Messages API de Vonage en un caso de uso práctico.
¿Tienes alguna pregunta o algo que compartir? Únete a la conversación en Slack de la comunidad de Vonagey mantente actualizado con el Boletín para desarrolladoressíguenos en X (antes Twitter)suscríbete a nuestro canal de YouTube para ver tutoriales en video, y sigue la página de página para desarrolladores de Vonage en LinkedInun espacio para que los desarrolladores aprendan y se conecten con la comunidad. Mantente conectado, comparte tu progreso y entérate de las últimas noticias, consejos y eventos para desarrolladores.
Compartir:
Karl es un defensor de los desarrolladores para Vonage, centrado en el mantenimiento de nuestros SDK de servidor Ruby y la mejora de la experiencia de los desarrolladores para nuestra comunidad. Le encanta aprender, hacer cosas, compartir conocimientos y, en general, todo lo relacionado con la tecnología web.