Hlavní navigace

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

Jakub Šťastný 9. 7. 2007

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?

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.

Našli jste v článku chybu?

9. 7. 2007 8:17

Tomas (neregistrovaný)
no je to to samy jako u ostatnich jazyku...
ruby -> gems
python -> easy_install / setuptools
perl -> cpan
php -> pear
bud puzivas nejaky takovyho balickovaci a instalacni system prislusneho jazyk a nebo puzivas systemove balicky.
- osobne pouzivam na produkcnich strojich, kde mam vetsinou debian, systemove deb-balicky.

ale na pocitaci, na kterym vyvijim to instaluju pres gems a podobne systemy, protoze je to rychlejsi, nemusim vytvret balicky co nejsou ve stable systemu, jsou …







9. 7. 2007 0:17

hunki punki - wtf ?! (neregistrovaný)
gem me vzdycky prisel dost rozporuplny. Hlavni blbost toho je ze se mi o bezpecnosti updaty nestara system. A pridanim jednoho radku do cronu se to fakt nevyresi. Jinak receno, bojim se toho, ze kvuli gem nebalickuji balickovaci knihovny pro ruby - coz neni vubec prijemne.
Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Root.cz: Vypadl Google a rozbilo se toho hodně

Vypadl Google a rozbilo se toho hodně

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

Podnikatel.cz: EET zvládneme, budou horší zákony

EET zvládneme, budou horší zákony

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život