Hlavní navigace

Utilitky pro Ruby: balíčkovací systém RubyGems podruhé

9. 7. 2007
Doba čtení: 4 minuty

Sdílet

V dnešním díle seriálu o utilitkách pro Ruby se budeme opět věnovat balíčkovacímu systému RubyGems. Naučíme se, jak využívat knihoven distribuovaných skrze RubyGems a dokonce si povíme o fintách, které nám umožní přesně specifikovat, které verze knihovny je možné pro projekt použít.

Využíváme knihoven instalovaný pomocí RubyGems

Knihovny, které nainstalujeme pomocí RubyGems, nejsou dostupné v klasické cestě rubyovských knihoven, a jejich volání v programech tedy nutně končí výjimkou LoadError. Je tomu tak proto, aby bylo možno spravovat více verzí knihoven zároveň. Technicky se jedná o stejný systém jako sloty v distribuci Gentoo. Dejme tomu, že jsme si pomocí RubyGems nainstalovali jednu z knihoven pro protokol XMPP a chceme ji nyní použít ve svém programu, což může být dejme tomu třeba jabberovský bot. Nejprve ji zkusíme použít stejným způsobem, jako se to dělá se systémovými knihovnami:

#!/usr/bin/env ruby
require "xmpp4r"
...
3485> ./gems.rb
./gems.rb:4:in `require': no such file to load -- xmpp4r (LoadError)
        from ./gems.rb:4

Jak vidíte, program opravdu skončil výše zmíněnou výjimkou. Nyní si to vyzkoušíme s načtením knihovny rubygems pomocí metody require:

#!/usr/bin/env ruby
require "rubygems"
require "xmpp4r"
...
3487> ./gems.rb
3488>

Jak je vidno, tato alternativa již funguje, ale za předpokladu, že nevíme, zda se bude volat knihovna z RubyGems či ze systému, je lepší to řešit jiným způsobem. Například volbou -rubygems předanou interpretu Ruby:

#!/usr/bin/env ruby
require "xmpp4r"
...
3490> ruby -rubygems gems.rb
3491>

Co se týče tohoto řešení, je na místě zmínit, že se nejedná vlastně o parametr rubygems, nýbrž o parametr r s hodnotou ubygems. Ano, opravdu se knihovna jmenuje (také) ubygems, ostatně podívejte se sami do svých rubyovských knihoven. V souboru ubygems.rb naleznete volání knihovny rubygems, jinými slovy se jedná o pouhou pomůcku, protože parametr rubygems vypadá lépe nežli rrubygems. Funguje ale obojí, jak si ostatně můžete vyzkoušet sami. Nicméně ani toto není nejlepší způsob, kdo by se s tím pořád psal, a proto sáhneme do svého /etc/profile a exportujeme proměnnou RUBYOPT:

#!/usr/bin/env ruby
require "xmpp4r"
...
3493> export RUBYOPT="rubygems"
3494> ./gems.rb
3495>

Vidíte? Funguje to. Abych ale zmíněný příklad vysvětlil – opět se jedná o to samé, a sice o načtení knihovny rubygems, tentokrát však automaticky při každém spuštění interpretu Ruby, zajištěné proměnnou prostředí RUBYOPT.

Požadavek na určitou verzi knihovny

RubyGems umožňují načtení konkrétní verze knihovny. Jedná se o velmi sofistikovaný systém, který umožňuje nejenom načíst jistou knihovnu ve verzi kupříkladu 0.4, ale třeba také knihovnu v kterékoliv verzi vyjma 0.4.5, knihovnu ve verzi vyšší než 0.2 a podobně. Použití je jednoduché:

gem <knihovna> <verze>

… tedy například:

  gem 'RedCloth', '> 3.0'   # načti knihovnu RedCloth ve verzi vyšší než 3.0
  gem 'rails', '= 0.9.3'    # načti knihovnu rails právě ve verzi 0.9.3

Je na místě připomenout, že metoda gem očekává parametry třídy String a že verze rovná námi specifikované verzi se požaduje pomocí rovná se, nikoliv dvou rovná se vedle sebe, jak by programátoři spíše očekávali. Nenajde-li systém RubyGems požadovanou verzi, vyvolá výjimku.

Již několikrát jsem řekl, že RubyGems jsou skutečně sofistikovaný systém správy balíčků, a je tomu opravdu tak. Pokud vás náhodou dosud uvedený výčet možností nepřesvědčil, toto už opravdu musí. Může se stát, že naše podmínky pro specifikaci knihovny jsou velmi složité a že s prostou specifikací verze, verze větší než uvedenou a podobně si již nevystačíte. V tom případě vám nic nebrání zadat parametrů více, čím už můžete dosáhnout opravdu čehokoliv:

gem 'library', '>= 2.2.0', '< 3.0'
V dřívějších verzích RubyGems se pro načtení knihoven dostupných z gemů používala metoda require_gem, je to tak stále zmiňováno i v oficiální dokumentaci, nicméně je to zastaralé a měla by se na vše používat metoda gem
Znak Význam
= požaduje konkrétní číslo verze
!= kteroukoliv jinou verzi než uvedenou
> větší než uvedenou
< menší než uvedenou
>= větší nebo rovnu uvedené
<= menší nebo rovnu uvedené
~> spíše větší než uvedená verze

Tabulka možných specifikací verzí.

Software je živý organismus, neustále se vyvíjí. Požadované verze knihoven se mění a někdy by se dokonce hodilo, kdyby specifikace konkrétních verzí mohla být spíše v konfiguračním souboru, než přímo v kódu aplikace.

Konfigurační soubor config.yml:

---
:gems:
  - ['RedCloth', '~> 3.0']
  - ['rubyzip', '= 0.5.5']

Kód k načtení a zpracování konfiguračního souboru:

config = open("config.yml") do |file|
  YAML::load(file)
end

if config[:gems]
  require 'gemconfigure'
  Gem.configure(config[:gems])
end

Myslím, že zde není co vysvětlovat. V konfiguračním souboru specifikujeme výše uvedeným způsobem požadované verze, načteme knihovnu gemconfigure a metodou Gem.configure knihovny načteme. Jednoduché a efektivní, co víc si přát?

CS24_early

Příště

Zatímco dnes jsme se na RubyGems podívali jako programátoři, kteří právě potřebují využít knihovny distribuované skrze RubyGems, příště se (už opravdu) naučíme tvořit vlastní Gemy, naučíme se je podepisovat a dokonce si i ukážeme, jak je možné vytvořit a síťově zpřístupnit vlastní repozitář gemů.

Poznámka: některé ukázky byly přejaty z oficiální dokumentace k systému RubyGems.

Byl pro vás článek přínosný?

Autor článku

Jakub Šťastný byl v letech 2007 až 2008 redaktorem serveru Root.cz. Mezi jeho zájmy patří Linux, programování a typografický systém TeX.