RubyGems: ¿Cómo crear tu gema? (5)

Crear y publicar su propia gema es simple gracias a las herramientas integradas directamente en RubyGems.

¡Hagamos una gema simple de “hola mundo” y siéntete libre de jugar con ello como quieras!

El código de la gema que vamos a hacer aquí está en GitHub.

Tu primera GEMA

Empieza con un solo archivo de Ruby para tu gema hola y el archivo gemspec.

Vas a necesitar un nuevo nombre para el tuyo (quizás `hola_tunombre) para luego publicarlo.

Consulta la guía de patrones para conocer las recomendaciones básicas a seguir al nombrar una gema.

% tree
.
├── hola.gemspec
└── lib
└── hola.rb

El código para tu paquete se coloca dentro del directorio lib .

La convención es tener un archivo de Ruby con el mismo nombre que tu gema, ya que se carga cuando se ejecuta require 'hola' .

Ese archivo está a cargo de configurar el código y la API de tu gema.

El código dentro de lib/hola.rb es bastante simple. Solo se asegura de que puedas ver algún resultado de la gema:

% cat lib/hola.rb
class Hola
def self.hi
puts "Hello world!"
end
end

La gemspec define qué hay en la gema, quién la hizo y la versión de la gema; también es su interfaz para RubyGems.org .

La información que ves en una página de gemas (como la de jekyll) proviene del archivo gemspec.

% cat hola.gemspec
Gem::Specification.new do |s|
s.name        = 'hola'
s.version     = '0.0.0'
s.summary     = "Hola!"
s.description = "A simple hello world gem"
s.authors     = ["Nick Quaranto"]
s.email       = '[email protected]'
s.files       = ["lib/hola.rb"]
s.homepage    =
'https://rubygems.org/gems/hola'
s.license       = 'MIT'
end

El miembro de la descripción puede ser mucho más largo de lo que ve en este ejemplo. Si coincide /^== [A-Z]/ , la descripción se ejecutará a través del formateador de marcado de RDoc para mostrarse en el sitio web de RubyGems. Sin embargo, tenga en cuenta que es posible que otros consumidores de los datos no entiendan este marcado.

El gemspec también es Ruby, por lo que puede envolver scripts para generar los nombres de los archivos y aumentar el número de versión.

Hay muchos campos que puede contener gemspec. Para verlos todos echa un vistazo a la referencia completa.

Después de haber creado una gemspec, puede construir una gema a partir de ella. Luego puede instalar la gema generada localmente para probarla.

% gem build hola.gemspec
Successfully built RubyGem
Name: hola
Version: 0.0.0
File: hola-0.0.0.gem
% gem install ./hola-0.0.0.gem
Successfully installed hola-0.0.0
1 gem installed

Por supuesto, la prueba de humo aún no ha terminado: el último paso es buscar la gema mediante require para usarla:

% irb
>> require 'hola'
=> true
>> Hola.hi
Hello world!

Si estás utilizando una versión anterior de Ruby a la 1.9.2, debes iniciar la sesión irb -rubygems o solicitar la biblioteca de rubygems después de iniciar irb.

Ahora puedes compartir hola con el resto de la comunidad de Ruby.

Publicar tu gema en RubyGems.org solo requiere un comando, siempre que tengas una cuenta en el sitio.

Para configurar su computadora con tu cuenta de RubyGems, puedes ejecutar el siguiente comando (donde nombreusuario debe ser reemplazado por tu propio nombre de usuario):

$ curl -u nombreusuario https://rubygems.org/api/v1/api_key.yaml >
~/.gem/credentials; chmod 0600 ~/.gem/credentials
Enter host password for user 'qrush':

Si tiene problemas con curl, OpenSSL o certificados, simplemente intente ingresar la URL anterior en la barra de direcciones de su navegador. El navegador te pedirá que inicies sesión en RubyGems.org. Introduce tu nombre de usuario y contraseña. El navegador ahora intentará descargar el archivo api_key.yaml. Guárdalo en ~/.gem y llámalo ‘credenciales’

Una vez que eso se haya configurado, puedes sacar la gema:

% gem push hola-0.0.0.gem
Pushing gem to RubyGems.org...
Successfully registered gem: hola (0.0.0)

En poco tiempo (generalmente menos de un minuto), la gema estará disponible para que cualquier persona la instale.

Puedes verlo en el sitio RubyGems.org o obtenerla desde cualquier computadora con RubyGems instalado:

% gem list -r hola
*** REMOTE GEMS ***
hola (0.0.0)
% gem install hola
Successfully installed hola-0.0.0
1 gem installed

Así de fácil es compartir código con Ruby y RubyGems.

Requerir más archivos

El tener todo en un solo archivo no escala bien. Por lo que agregaremos un poco más de código a nuestra GEMA.

% cat lib/hola.rb
class Hola
def self.hi(language = "english")
translator = Translator.new(language)
translator.hi
end
end
class Hola::Translator
def initialize(language)
@language = language
end
def hi
case @language
when "spanish"
"hola mundo"
else
"hello world"
end
end
end

Este archivo se está llenando bastante por lo que lo dividiremos. Pasemos Translator a un archivo separado.

Como se mencionó anteriormente, el archivo raíz de la gema se encarga de cargar el código de la gema.

Los otros archivos de una gema generalmente se colocan en un directorio con el mismo nombre de la gema dentro de lib .

Por tanto, vamos a poder dividir la gema así:

% tree
.
├── hola.gemspec
└── lib
├── hola
│   └── translator.rb
└── hola.rb

El Translator está ahora en lib/hola que se puede recoger fácilmente con una declaración require de lib/hola.rb .

El código para Translator no cambió mucho:

% cat lib/hola/translator.rb
class Hola::Translator
def initialize(language)
@language = language
end
def hi
case @language
when "spanish"
"hola mundo"
else
"hello world"
end
end
end

Pero ahora el archivo hola.rb tiene un código para cargar el Translator :

% cat lib/hola.rb
class Hola
def self.hi(language = "english")
translator = Translator.new(language)
translator.hi
end
end
require 'hola/translator'

Para la carpeta/archivo recién creado, no olvide agregar una entrada en el archivo hola.gemspec, como se muestra-

% cat hola.gemspec
Gem::Specification.new do |s|
...
s.files       = ["lib/hola.rb", "lib/hola/translator.rb"]
...
end

Sin el cambio anterior, la nueva carpeta no se incluiría en la gema instalada.

Probemos esto. Primero, enciende irb :

% irb -Ilib -rhola
irb(main):001:0> Hola.hi("english")
=> "hello world"
irb(main):002:0> Hola.hi("spanish")
=> "hola mundo"

Necesitas usar un indicador de línea de comando extraño aquí: -Ilib . Por lo general, RubyGems incluye el directorio lib por ti, por lo que los usuarios finales no necesitan preocuparse por configurar las rutas de carga.

Sin embargo, si estás ejecutando el código fuera de RubyGems, debes configurar las cosas por tu propia cuenta.

Es posible manipular $LOAD_PATH desde dentro del propio código, pero se considera un antipatrón en la mayoría de los casos.

Hay muchos más antipatrones (¡y buenos patrones!) para gemas, explicados en esta guía .

Si has agregado más archivos a la gema, asegúrate de recordar agregarlos a la matriz de tu gemspec files antes de publicar una gema nueva.

Por esta razón (entre otras) muchos desarrolladores automatizan esto con Hoe, Jeweller, Rake, Bundler o simplemente una gemspec dinámica .

Agregar más directorios con más código desde aquí es prácticamente el mismo proceso. ¡Divide tus archivos de Ruby cuando tenga sentido!

Agregar un ejecutable

Además de proporcionar bibliotecas de código Ruby, las gemas también pueden exponer uno o varios archivos ejecutables en el archivo PATH .

Probablemente el ejemplo más conocido de esto es rake . Otro muy útil es prettify_json.rb , incluido con la gema JSON que formatea JSON de manera legible (y se incluye con Ruby 1.9).

Aquí hay un ejemplo:

% curl -s http://jsonip.com/ | \
prettify_json.rb
{
"ip": "24.60.248.134"
}

Agregar un ejecutable a una gema es un proceso simple. Solo necesitas colocar el archivo en el directorio bin de una gema y luego agregarlo a la lista de ejecutables en gemspec.

Agreguemos uno para la gema Hola. Primero crea el archivo y hazlo ejecutable:

% mkdir bin
% touch bin/hola
% chmod a+x bin/hola

El archivo ejecutable en sí solo necesita un shebang para averiguar con qué programa ejecutarlo. Así es como se ve el ejecutable de Hola:

% cat bin/hola
#!/usr/bin/env ruby
require 'hola'
puts Hola.hi(ARGV[0])

Todo lo que hace es cargar la gema y pasar el primer argumento de la línea de comando como el idioma para saludar. Aquí hay un ejemplo de cómo ejecutarlo:

% ruby -Ilib ./bin/hola
hello world
% ruby -Ilib ./bin/hola spanish
hola mundo

Finalmente, para incluir el ejecutable de Hola cuando presionas la gema, deberás agregarlo en gemspec.

% head -4 hola.gemspec
Gem::Specification.new do |s|
s.name        = 'hola'
s.version     = '0.0.1'
s.executables << 'hola'

Empuje hacia arriba esa nueva gema, ¡y tendrás tu propia utilidad de línea de comandos publicada! También puedes agregar más ejecutables en el directorio bin si lo necesitas, hay un campo executables de matriz en gemspec.

Ten en cuenta que debe cambiar la versión de la gema cuando publique una nueva versión. Para obtener más información sobre el control de versiones de gemas, consulte la Guía de patrones

Pruebas de escritura

Probar tu gema es extremadamente importante. No solo te ayuda a asegurarte de que tu código funciona, si no que ayuda a otros a saber que tu gema hace su trabajo.

Al evaluar una gema, los desarrolladores de Ruby tienden a ver un conjunto de pruebas sólido (o la falta de él) como una de las principales razones para confiar en esa pieza de código.

Las gemas admiten la adición de archivos de prueba en el propio paquete para que las pruebas se puedan ejecutar cuando se descarga una gema.

En resumen: ¡PRUEBA TU GEMA! ¡Por favor!

Minitest

es el framework de prueba integrado de Ruby. Hay muchos tutoriales para usarlo en línea.

También hay muchos otros frameworks de prueba disponibles para Ruby. RSpec es una de las opciones más populares.

Al final del día, no importa lo que uses, ¡solamente asegurar de realizar las PRUEBAS !

Agreguemos algunas pruebas a Hola. Esto requiere agregar algunos archivos más, a saber, un Rakefile y un directorio nuevo denominado test :

% tree
.
├── Rakefile
├── bin
│   └── hola
├── hola.gemspec
├── lib
│   ├── hola
│   │   └── translator.rb
│   └── hola.rb
└── test
└── test_hola.rb

Rakefile

brinda una automatización simple para ejecutar pruebas:

% cat Rakefile
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs << 'test'
end
desc "Run tests"
task :default => :test

Ahora puede ejecutar rake test o simplemente ejecutar pruebas con rake . Aquí hay un archivo de prueba básico para hola:

% cat test/test_hola.rb
require 'minitest/autorun'
require 'hola'
class HolaTest < Minitest::Test
def test_english_hello
assert_equal "hello world",
Hola.hi("english")
end
def test_any_hello
assert_equal "hello world",
Hola.hi("ruby")
end
def test_spanish_hello
assert_equal "hola mundo",
Hola.hi("spanish")
end
end

Finalmente, para ejecutar las pruebas:

% rake test
(in /Users/qrush/Dev/ruby/hola)
Loaded suite
Started
...
Finished in 0.000736 seconds.
3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
Test run options: --seed 15331

¡Si es verde! Es que la prueba se realizo con éxito. Para obtener más ejemplos excelentes, lo mejor que puede hacer es buscar en 100+forks%3A>10&type=Repositories&l=Ruby”>GitHub y leer algo de código.

Documentando el código

Por defecto, la mayoría de las gemas usan RDoc para generar documentos. Hay muchos tutoriales excelentes para aprender a marcar su código con RDoc.

Aquí tienes un ejemplo simple:

# The main Hola driver
class Hola
# Say hi to the world!
#
# Example:
#   >> Hola.hi("spanish")
#   => hola mundo
#
# Arguments:
#   language: (String)
def self.hi(language = "english")
translator = Translator.new(language)
puts translator.hi
end
end

Otra excelente opción para la documentación es YARD, ya que cuando envies una gema, RubyDoc.info genera YARDDocs automáticamente a partir de tu gema.

YARD es compatible con versiones anteriores de RDoc y tienes una buena introducción sobre las diferencias y cómo usarlo.


Conclusión

Con esta comprensión básica de la creación de su propia RubyGem, ¡Espero que estés en camino de crear tu propia gema!

Las siguiente guía cubre los patrones para hacer una gema y otras capacidades del sistema RubyGems.


<<

Relacionados

Deja un comentario