Ruby on Rails: Exceptions
Každý programátor by měl znát výjimky. Výjimky nám můžou pomoci vyklouznout ze situací, které jsou pro program kritické, můžeme pomocí nich ošetřit vzniklou chybu, ať uživatelskou, nebo systémovou.
Pro názornou ukázku si vyzkoušejme tento příklad, tedy jednoduchou funkci, která vrací podíl dvou čísel:
1 2 3 |
def getDividing(x, y) return x/y; end |
Funkce je vpořádku, dva vstupní parametry dělí a vrací jejich podíl. Při testování aplikace vám bude zřejmě taky všechno fungovat vpořádku, až do případu, kdy nastane obdobné volání:
1 |
getDividing(1, 0) |
a program vypíše chybovou hlášku:
1 |
ZeroDivisionError (divided by 0) |
Tato situace je nepříjemná, a je nutno ji ošetřit, pro případ, že by k ní docházelo znova, protože toto chování programu je nepřípustné.
Ruby pro tento případ nabízí řešení v podobě nástroje k ošetření výjimek, stejně jako většina pokročilýchprogramovacích jazyků.
Tím jsme si tedy stručně vysvětlili, co to výjimky vlastně vůbec jsou a můžeme se podívat jak se s nimi vypořádat v ruby.
Ruby on Rails – Rescue (Ensure)
Výjimky v Ruby on Rails mají konstrukci obdobnou této:
1 2 3 4 5 |
begin code rescue Exception => ex code end |
Celý blok kódu, ve kterém může výjimka nastat (tedy ten blok, ve kterém očekáváme, že by mohla nastat chyba) je uzavřen v bloku begin…end. Tento blok je kontrolován na výjimku a v případě že nastane, přejde do bloku rescue, kde může být výjimka ošetřena.
Pokud bychom měli tuto konstrukci použít na našem ukázkovém příkladu, mohla by být jeho funkčnost například taková (v závislosti na požadované funkčnosti):
1 2 3 4 5 6 7 8 9 |
def getDividing(x, y) begin return x/y; rescue Exception => e #save into log file save_log e.message return 0 end end |
Nyní v případě dělení nulou dostaneme nulový výsledek, což sice není správně, ale ošetříme tím chybu, která jinak vznikla a byla pro aplikaci kritická – způsobila zhroucení programu.
Kromě této konstrukce můžeme samozřejmě použít ještě finální blok, který se provede vždy za všech okolností, v případě výjimky, ale i v případě že výjimka nenastane. Tento blok je uvozen příkazem ensure a náš příklad bychom přepsali například takto:
1 2 3 4 5 6 7 8 9 10 11 12 |
def getAbsDividing(x, y) begin dividing = x/y; rescue dividing = 0 ensure #absolute value dividing = dividing.abs end return dividing end |
Funkci jsme upravili tak, aby vracela absolutní hodnotu z dělení dvou čísel. Tato funkce funguje následně tak, že se snaží dělit dvě čísla. Pokud se dělení nepovede, vyvolá se výjimka a výsledek dělení bude 0. V každém případě se tento výsledek převede na absolutní hodnotu a je funkcí navrácen.
Jaká že to nastala výjimka? – $!
V případě že nevíte, jaká výjimka nastala, ale chcete toto rozhodnutí nechat na interpretu jazyka, můžete použít magickou proměnnou: $!, která obsahuje text vyvolané výjimky tak, jak o ní rozhodl interpret:
1 2 3 4 5 |
begin File.open("file.xml", "r") rescue puts $! end |
V případě neexistujícího souboru file.xml program vypíše:
1 |
No such file or directory - file.xml |
Vyvolání výjimky
Samozřejmě kromě ošetření výjimek je možné výjimky i vyvolat. K této operaci slouží v RoR příkaz raise, který vyvolá chybu uvedenou v jeho definici:
1 2 3 4 5 |
begin raise "wtf?" rescue Exception => e puts e.message end |
Závěrem
Používání výjimek by měl znát každý programátor, protože při správném používání může snadno ušetřit ve slabých místech programů zbytečné problémy.