Ruby Gems, Gemfile & Bundler (The Ultimate Guide)

¿Qué es una gema de Ruby?

Una gema es un paquete que puedes descargar &instalar. Cuando necesitas una gema instalada estás añadiendo funcionalidad extra a tu programa Ruby.

Las gemas te permiten:

  • Añadir una función de login a tu aplicación Rails
  • Trabajar fácilmente con servicios externos (como APIs)
  • Construir una aplicación web

Estos son sólo algunos ejemplos. Cada gema tiene su propio objetivo.

¿Por qué usamos gemas?

  • Es la forma de compartir bibliotecas &herramientas en Ruby
  • El formato de la estructura de archivos &de una gema hace que sea fácil entender cómo funcionan
  • Un archivo de especificación («.spec») que viene con cada gema describe las dependencias (otras gemas requeridas) para que el código tenga todo lo que necesita para funcionar

Gracias a RubyGems, tenemos un rico ecosistema de bibliotecas útiles a sólo un gem install de distancia!

Una lista de gemas requeridas para un determinado proyecto (no gema) puede ser listada en un archivo especial llamado «Gemfile» para que puedan ser instaladas automáticamente por Bundler. Ambas cosas se tratan más adelante en esta guía.

¿Cuáles son algunos ejemplos de gemas?

  • Rails, y todos sus componentes (ActiveRecord, ActiveSupport, etc.) se distribuyen como gemas Ruby
  • Pry, la potente alternativa a irb
  • Nokogiri, un popular analizador XML & HTML

La mayoría de las gemas son código Ruby puro.

Unas pocas gemas incluyen una extensión Ruby C para mejorar el rendimiento.

Esta extensión se construye automáticamente para ti cuando instalas la gema. En algunos casos, puedes necesitar instalar manualmente software adicional que no es gestionado por RubyGems.

Ahora:

Aprendamos más sobre las gemas construyendo tu propia & mirando los archivos que forman una gema.

Cómo construir una RubyGem

Puedes preparar los archivos para una nueva gema ejecutando bundle gem <name>.

Por ejemplo:

bundle gem awesome_gem

Una Gema está compuesta por la siguiente estructura:

├── awesome_gem.gemspec├── bin│ ├── console│ └── setup├── Gemfile├── lib│ ├── awesome_gem│ │ └── version.rb│ └── awesome_gem.rb├── Rakefile├── README.md└── test ├── awesome_gem_test.rb └── test_helper.rb

Este archivo .gemspeces donde encontrarás toda la información sobre la gema.

Incluye:

  • Nombre de la gema
  • Resumen de la gema (breve descripción)
  • Nombre del autor
  • Lista de dependencias
  • Lista de archivos a incluir en la gema
  • Opcional: Dirección de correo electrónico del autor, URL del proyecto (página de inicio), ejecutables, extensiones c, descripción larga.

La propia versión de la gema se define como una constante en lib/<gem_name>/version.rb.

Aquí tienes un ejemplo de gemspec:

Gem::Specification.new do |spec| spec.name = "awesome_gem" spec.version = AwesomeGem::VERSION spec.authors = spec.summary = "Example gem for article about Ruby gems" spec.files = Dir.grep_v(/.gem$/) spec.require_paths = spec.add_development_dependency "bundler", "~> 1.16" spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "minitest", "~> 5.0"end

La matriz require_paths es donde Ruby buscará tus archivos de gemas cuando los requieras. Esto te permite poner tu código bajo lib/<gem_name>/ & y luego requerirlo con require "<gem_name>/<file_name>".

Por ejemplo:

Un archivo llamado lib/awesome_gem/parser.rb sería requerido como require "awesome_gem/parser" desde cualquier lugar dentro de la gema.

Tendrás la mayoría de tus requerimientos en lib/<gem_name>.rb (el único archivo en la raíz de /lib).

¡Ese es el archivo que se carga cuando require la gema!

Siguiente:

Las líneas add_development_dependency definen gemas que vas a utilizar durante el desarrollo.

Estas son gemas como minitest, RSpec, o pry.

Mientras que add_dependency define gemas que utilizas como parte de tu código.

Una vez que hayas cambiado la descripción del resumen & de los valores por defecto… podrás cargar una sesión irb con tu gema usando el programa bin/console que bundle gem crea para ti.

Ejemplo:

$ bin/consoleirb(main):001:0>irb(main):002:0>irb(main):003:0> AwesomeGem=> AwesomeGemirb(main):004:0>irb(main):005:0> AwesomeGem::VERSION=> "0.1.0"

Entonces puedes empaquetar la gema usando gem build <name>.gemspec & publicarla en rubygems.org usando gem push.

¿Qué es Bundler?

Mientras aprendes sobre las gemas de Ruby puede que también leas sobre Bundler.

¿Pero qué es Bundler exactamente?

Bundler es una herramienta para la gestión de dependencias.

¿No se encargaba ya RubyGems de esto?

Bueno, lo hace… pero sólo para las propias gemas.

Tu aplicación Ruby normal no está construida como una gema, así que no tiene esta característica.

¡Por eso existe Bundler!

Entendiendo los Gemfiles

¿Has visto esos archivos Gemfile?

Es donde escribes qué gemas quieres usar para tu aplicación Ruby.

Estas gemas se cargarán por ti sin tener que requirelas mismas.

Un Gemfile se parece a esto:

ruby '2.5.0'gem 'rails', '~> 5.2.1'gem 'sqlite3'gem 'puma', '~> 3.11'gem 'bootsnap', '>= 1.1.0', require: false

Bundler (y RubyGems desde la versión 2.0) puede leer este archivo &instalar las versiones solicitadas de estas gemas.

Esto es lo que deberías ver al ejecutar el comando bundle install:

Using turbolinks-source 5.1.0Using turbolinks 5.1.1Using uglifier 4.1.18Using web-console 3.6.2Bundle complete! 18 Gemfile dependencies, 78 gems now installed.Use `bundle info ` to see where a bundled gem is installed.

Ahora:

¿Qué son estos símbolos (como ~>) que se usan al declarar las versiones para cada gema en tu Gemfile?

Estos te permiten solicitar un rango de versiones.

Puedes decir cosas como, «Quiero que la versión sea igual o mayor que 1.2, pero menor que 2.0».

Lo que se vería así:

gem 'puma', '~> 1.2'

El ~> es un atajo para este rango:

gem 'puma', '>= 1.2', '

In the case of , it means exactly this:

'>= 5.2.1', '

The more specific the version number is the more restricted the version range will be.

Gemfile Options & Gemfile.lock

You have a few options when requiring a gem inside a Gemfile.

For example:

You may want to pull a gem from a different source, like GitHub.

This is helpful when you need to use the latest version of the project, even if it hasn't been released on rubygems.org yet.

Here's an example:

gem "rails", git: "[email protected]:rails/rails.git"

Puedes pasar una opción branch para usar el código de una rama que no sea master.

gem "awesome_print", git: "[email protected]:awesome-print/awesome_print.git", branch: "v2"

Otra opción que puedes encontrar es require: false.

¿Qué hace eso?

Le dice a Bundler que no auto-requiera la gema por ti. Esto significa que tendrás que requireintroducirla en tu código cuando la necesites.

Esto se utiliza para gemas que tienen un alcance limitado.

Por ejemplo:

Gemas que utilizas en una tarea específica de rake, pero que no utilizas en tus modelos de controladores Rails &. La ventaja es que ahorras memoria en el código de tu aplicación porque sólo cargas esa gema cuando la necesitas.

También puedes agrupar gemas por entorno.

Eso significa que puedes tener gemas que sólo se instalan &cargadas en desarrollo (como capybara & pry).

Finalmente, bundler crea un Gemfile.lock.

¿Cuál es la diferencia?

Un Gemfile.lockse autogenera &dice exactamente qué versiones de cada gema fueron instaladas.

Bundler instalará estas versiones para que cuando despliegues esta aplicación en producción, o compartas tu proyecto con otros desarrolladores, todos trabajen con un conjunto idéntico de gemas.

Comandos útiles de Bundler

Comando Descripción
Lista de gemas Lista todas sus gemas instaladas. Acepta un argumento para filtrar gemas por nombre (ejemplo: gem list active)
gem which <nombre> Da la ruta donde está instalada una gema.
gem search <nombre> Busca gemas desde fuentes configuradas (por defecto: rubygems.org). Toma una expresión regular (ejemplo: gem search "\Aawesome_").
gem env Muestra información sobre su entorno de gemas (versión, rutas, configuración).
gem install <nombre> -v <versión> Le permite instalar una versión específica de gemas (ejemplo: gem install sinatra -v 2.0.0).
bundle viz Genera una visualización del gráfico de dependencias de su proyecto actual.
bundle show Muestra información sobre una gema concreta instalada a través de bundler. Debe estar dentro de una carpeta con un Gemfile.
bundle outdated Muestra una lista de gemas obsoletas en el proyecto actual. Puede usar la opción --groups para agruparlas.
bundle console Ejecuta una sesión irb con las gemas del Gemfile del proyecto actual.

Resumen

Has aprendido sobre RubyGems, el sistema de paquetes para Ruby. También has aprendido cómo se estructura una gema, qué es un Gemfile, Bundler & la diferencia entre el Gemfile & el Gemfile.lock.

¡Espero que hayas encontrado esto útil!

Deja una respuesta

Tu dirección de correo electrónico no será publicada.