Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

Ruby v příkladech (3) - Začínáme s aplikací

Podívejme se, jak vytvořit aplikaci, která po zadání (křestního) jména vrátí měsíc a den, kdy má osoba s tímto jménem svátek (a naopak). Ze všeho nejdříve si ale vytvoříme knihovní modul, který bude implementovat logiku aplikace, a také si ukážeme, jak se (lehce) napíší jednotkové testy (unit tests).

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Jak na aplikaci

Budeme pracovat s touto datovou strukturou: { ... 'Karina' => [2,1], 'Radmila' => [3,1], ... }. Jména budou tedy tvořit klíče hashe (asociativního pole), hodnoty budou dvouprvková pole obsahující vždy číslo dne v měsíci (1 až 31) a číslo měsíce (1 až 12). Jedná se však o velké množství dat. Raději je tedy oddělíme od vlastního kódu aplikace a uložíme v externím souboru ve formátu YAML. Soubor reprezentující výše zmíněný hash bude vypadat takto:

---
Nový rok:
 - 1
 - 1
Karina:
 - 2
 - 1
Radmila:
 - 3
 - 1
Diana:
 - 4
 - 1
... 

Následujících necelých 20 řádků kódu implementuje načtení dat ze souboru, hledání dne a měsíce podle jména a hledání jména podle dne a měsíce:

 1:  module Jmeniny
 2:    require 'yaml'
 3:
 4:    data_dir = File.dirname(__FILE__)
 5:    File.open( "#{data_dir}/jmeniny.yaml" ) do |yf|
 6:      @@seznam = YAML::load(yf)
 7:    end

 8:
 9:    def Jmeniny.den(jmeno)
10:      @@seznam[jmeno]
11:    end
12:
13:    def Jmeniny.jmeno(den, mesic)
14:      vyber = @@seznam.select{ |jmeno, datum| datum==[den,mesic] }
15:      return nil if vyber == []
16:      return vyber.map{ |pole| pole[0] }.inject do |memo, jmeno|
17:        memo.length > jmeno.length ? memo : jmeno
18:      end

19:    end
20:
21:  end 

Celá logika aplikace je obsažena v modulu Jmeniny, který začíná deklarací na řádku 1. Další řádek vkládá nástroje pro práci se soubory ve formátu YAML. Na řádku 4 zjišťujeme, kde (tj. ve kterém adresáři) je skript uložen. __FILE__ je pseudoproměnná obsahující název souboru se zdrojovým kódem. Datový soubor jmeniny.yaml má být totiž umístěn ve stejném adresáři. Při otevírání datového souboru (řádek 5) proto musíme zadat jméno souboru i s adresářem. Jinak bychom nemohli jednoduše volat výslednou aplikaci z jiného adresáře.

Všimněte si, že za otevřením souboru se vyskytuje blok (konec řádku 5 a řádky 6 a 7), ve kterém se s otevřeným souborem manipuluje prostřednictvím proměnné yf. Takovéto použití bloku pro práci s externími zdroji (soubory, databázová spojení apod.) je v Ruby typické. Konec bloku pak automaticky uvolňuje externí zdroj (v našem případě zavírá otevřený soubor), aniž by se o to programátor musel nějak zvlášť starat.

Proměnná @@seznam (ř. 6) je (díky dvojitému zavináči) proměnná třídy (něco jako privátní statický atribut třídy v jiných programovacích jazycích).

Metoda Jmeniny.den (řádky 9 až 11) je opravdu primitivní. Jako jediný parametr očekává řetězec se jménem. Výsledkem výrazu @@seznam[jmeno] je pak dvouprvkové pole den a měsíc (nebo nil, pokud se jméno v hashi @@seznam nevyskytuje). Protože je to zároveň i poslední výraz v metodě, jeho hodnota je i návratovou hodnotou celé metody.

Zde bych chtěl upozornit, že název metody začíná „ Jmeniny.“ (tedy názvem modulu). Jde tedy o metodu modulu. Metody modulu (resp. metody tříd) se vztahují k samotnému modulu (resp. třídě), nikoliv k instancím.

Metoda Jmeniny.jmeno (řádky 13 až 19) je o něco komplikovanější. Očekává dva parametry – číslo dne a měsíce. Protože hash @@seznam je seřazený podle jména a nikoliv podle data, nezbývá než projít celý hash a metodou select vybrat všechny páry [jméno, [den,měsíc]], pro které se den a měsíc shodují s hledanými (řádek 14). Pokud je pole prázdné, metoda končí a vrátí nil (řádek 15). Menší komplikací je, že některé kombinace dne a měsíce vracejí více než jedno jméno. Je tomu tak v případech, kdy v daném dni má svátek více osob. Například při volání Jmeniny.jmeno(29, 6) bude proměnná vyber obsahovat pole, jehož prvky jsou pole s páry jméno, datum: [ ['Petr', [29, 6] ], ['Pavel', [29, 6] ], ['Petr a Pavel', [29, 6] ] ]. Správný výsledek je zjevně 'Petr a Pavel'. Je tedy potřeba vyhledat to nejdelší jméno (řádky 16 až 18). Metoda map

volá blok na každý element výše uvedeného pole – tedy nejprve na [‚Petr‘,
[29, 6] ], pak na [‚Pavel‘, [29, 6] ] atd. Výsledkem každé iterace (blok
na řádku 16) je pole[0], což je řetězec se jménem. Výsledkem
všech iterací je pak posloupnost těchto jmen. Na ni je možné
aplikovat metodu inject,
což je metoda, která, podobně jako map,
aplikuje blok na prvky posloupnosti. Inject,
na rozdíl od map,
však používá i akumulátor pro zapamatování mezivýsledku. Hodnota obsažená
v akumulátoru na konci iterací je také výsledkem metody. Metodu inject

lze efektivně použít na úlohy typu sečtení posloupnosti čísel (např. výsledkem (5..10).inject {|sum, n| sum + n } je 45), nebo, jako v našem případě, k nalezení nejdelšího řetězce.

Rád bych také znovu upozornil na fakt, že v modulu (ale i třídě) lze poměrně volně míchat definice s kódem, který je prováděn okamžitě – tj. při načítání modulu (třídy) interpretem jazyka Ruby. V našem případě se kód z řádků 2 až 7 provádí okamžitě, řádky 9 až 19 jsou definice metod, jejichž kód se provede, až když je explicitně zavoláme. Tato vlastnost je v Ruby často využívána – např. pro automatické generování přístupových metod při definici tříd (viz např. metody attr_accessor , attr_reader , attr_writer ). Pokud bychom chtěli dosáhnout obdobného efektu v „běžných“ jazycích (např. Javě), bylo by nejspíše nutné rozšiřovat syntaxi (se všemi důsledky takového kroku).

Testování

Nyní se podívejme, jak snadno lze napsat jednotkové testy pro náš modul Jmeniny:

 1:  require 'test/unit'
 2:  require 'jmeniny'
 3:
 4:  class JmeninyTest < Test::Unit::TestCase
 5:
 6:    def test_den
 7:      assert_equal( [29, 6], Jmeniny.den("Petr") )
 8:      assert_equal( [29, 6], Jmeniny.den("Pavel") )
 9:      assert_equal( [29, 6], Jmeniny.den("Petr a Pavel") )
10:      assert_equal( [21, 8], Jmeniny.den("Johana") )
11:      assert_nil( Jmeniny::den("Bill") )
12:    end

13:
14:    def test_jmeno
15:      assert_equal( "Linda / Samuel", Jmeniny.jmeno(1, 9) )
16:      assert_equal( "Adam a Eva", Jmeniny.jmeno(24, 12) )
17:      assert_nil( Jmeniny.jmeno(33, 10) )
18:      assert_nil( Jmeniny.jmeno(6, 13) )
19:    end
20:
21:  end 

Programátoři více i méně extrémní určitě uvítají, že standardní knihovna Ruby obsahuje nástroje pro snadnou tvorbu jednotkových testů. Je to testovací framework Test::Unit . Testy jsou metody začínající na „ test_“ ve třídě odvozené z třídy Test::Unit::TestCase. Testy nejčastěji obsahují tvrzení (tj. volání metod assert_…), nicméně jsou to stále běžné metody, takže se v nich může vyskytovat libovolný kód.

Po spuštění výše uvedeného souboru s testy dostaneme takovouto statistiku:

davame_internetu_obsah
       
Loaded suite jmeniny-test
Started
..
Finished in 0.016 seconds.

2 tests, 9 assertions, 0 failures, 0 errors 

Máme tedy otestovaný modul, jehož metody umí k zadanému datu najít jméno a naopak. Příště se podíváme, jak tento modul použijeme v jednoduché konzolové aplikaci.

Pokud si mezitím začnete s Ruby hrát, můžete se podívat například na PLEAC- Ruby. Najdete zde desítky „receptů“ na řešení běžných programátorských problémů. Některé zde asi zaujme to, že stejný problém je zde obvykle řešen v Perlu, Pythonu, Ruby a případně i v jiných jazycích (je to však bohužel řazeno podle jazyků, nikoliv podle problémů).

Školení: Linux – Zálohování, Vysoká dostupnost, SNMP dohled

Na třídenním školení se naučíte nainstalovat a spravovat systém zálohování, replikace dat a vysoké dostupnosti dat. Dále také pracovat s RAID a LVM poli a nainstalovat a spravovat si vlastní dohledový systém.

Podrobnější informace a přihláška

Ohodnoťte jako ve škole:
Průměrná známka 2,95

Přehled názorů

Nekolik drobnosti ...
Wejn 22. 9. 2005 10:34
Nový
├ 
Re: Nekolik drobnosti ...
Pichi 22. 9. 2005 12:30
Nový
│
├ 
Re: Nekolik drobnosti ...
Igor 22. 9. 2005 13:59
Nový
│
│
└ 
Re: Nekolik drobnosti ...
Pichi 22. 9. 2005 14:15
Nový
│
└ 
Re: Nekolik drobnosti ...
Wejn 22. 9. 2005 16:36
Nový
│
 
└ 
Re: Nekolik drobnosti ...
Pichi 22. 9. 2005 18:06
Nový
│
 
 
├ 
Re: Nekolik drobnosti ...
Wejn 22. 9. 2005 18:58
Nový
│
 
 
│
├ 
Re: Nekolik drobnosti ...
anonymní uživatel 22. 9. 2005 19:14
Nový
│
 
 
│
│
├ 
Re: Nekolik drobnosti ...
YF 22. 9. 2005 19:53
Nový
│
 
 
│
│
│
└ 
Re: Nekolik drobnosti ...
anonymní uživatel 22. 9. 2005 21:00
Nový
│
 
 
│
│
└ 
Re: Nekolik drobnosti ...
ondrej 23. 9. 2005 02:16
Nový
│
 
 
│
│
 
├ 
Re: Nekolik drobnosti ...
anonymní uživatel 23. 9. 2005 07:43
Nový
│
 
 
│
│
 
│
└ 
Re: Nekolik drobnosti ...
Wejn 23. 9. 2005 09:09
Nový
│
 
 
│
│
 
└ 
Re: Nekolik drobnosti ...
pkm 23. 9. 2005 13:06
Nový
│
 
 
│
└ 
Re: Nekolik drobnosti ...
jrave 9. 10. 2005 10:03
Nový
│
 
 
│
 
├ 
Re: Nekolik drobnosti ...
Wejn 9. 10. 2005 13:07
Nový
│
 
 
│
 
│
├ 
Re: Nekolik drobnosti ...
anonymní uživatel 30. 10. 2005 09:41
Nový
│
 
 
│
 
│
└ 
Re: Nekolik drobnosti ...
jrave 30. 10. 2005 09:41
Nový
│
 
 
│
 
│
 
└ 
Re: Nekolik drobnosti ...
Wejn 30. 10. 2005 17:35
Nový
│
 
 
│
 
└ 
Re: Nekolik drobnosti ...
Pavel Sýkora 10. 10. 2005 09:50
Nový
│
 
 
│
 
 
└ 
Re: Nekolik drobnosti ...
jrave 30. 10. 2005 09:46
Nový
│
 
 
└ 
Re: Nekolik drobnosti ...
Petr Mach 26. 9. 2005 09:10
Nový
│
 
 
 
└ 
Re: Nekolik drobnosti ...
Pichi 27. 9. 2005 08:22
Nový
│
 
 
 
 
└ 
Re: Nekolik drobnosti ...
anonymní uživatel 27. 9. 2005 09:03
Nový
│
 
 
 
 
 
├ 
Re: Nekolik drobnosti ...
anonymní uživatel 27. 9. 2005 09:04
Nový
│
 
 
 
 
 
└ 
Re: Nekolik drobnosti ...
Wejn 27. 9. 2005 09:46
Nový
└ 
Re: Nekolik drobnosti ...
Pavel Sýkora 22. 9. 2005 15:43
Nový
 
└ 
Re: Nekolik drobnosti ...
Wejn 22. 9. 2005 16:39
Nový
RUBY a Ruby On Rails
klmn 22. 9. 2005 12:00
Nový
└ 
Re: RUBY a Ruby On Rails
Pavel Sýkora 22. 9. 2005 12:33
Nový
 
└ 
Re: RUBY a Ruby On Rails
klmn 22. 9. 2005 14:46
Nový
moda
Skeptik 22. 9. 2005 15:46
Nový
├ 
Re: moda
pf 22. 9. 2005 15:51
Nový
├ 
Re: moda
nibles 22. 9. 2005 15:52
Nový
└ 
Re: moda
pkm 23. 9. 2005 13:16
Nový
 
└ 
Re: moda
anonymní uživatel 23. 9. 2005 21:37
Nový
 
 
└ 
Re: moda
pkm 24. 9. 2005 00:02
Nový
Do Hajslíku, můžete zrušit ty čísla řádků!? Každýho to jen serre.
dd 17. 3. 19:36
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem