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?

Cloud 24 - tip 1

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.