Není-li jasné, co myslím pod pojmem framework, myslím nástroje či pomůcky, které umožní psát weby efektivněji než při tvoření v nízkoúrovňovém kódu. Frameworkem přitom může být jak kolekce samostatných tříd, tak celý složitý, provázaný systém, do jehož vnitřností proniknout by trvalo rok, a ani to není žádoucí.
Ruby on Rails znamená v překladu Ruby na kolejích. Budu o RoR proto psát spíše jako o nich.
Čím mne zaujaly Rails?
Uměl jsem Ruby a potřeboval jsem něco, co nebude příliš „robustní, efektivní, klikací a mocné“ (rozuměj přesložitělé) a nebudu se to muset učit půl roku, abych napsal Hello world. Zkoušel jsem různé frameworky, bohužel každý měl něco, co mne odrazovalo. Nakonec jsem se pokoušel o vlastní tvorbu, zůstalo to většinou u návrhů, které jsem později naštěstí zavrhl. Naštěstí proto, že kdybych pokračoval a až pak se setkal s Rails, promarnil bych čas.
V čem byly mé návrhy tak špatné? Z pohledu Rails jsem postupoval špatným směrem, jelikož jsem při návrhu nevycházel z potřeb praxe, nýbrž jsem se snažil praxi přizpůsobovat již hotovému nástroji. Takový postup vede ke složitému nástroji, který umí věci, jež vlastně v praxi nepotřebujeme.
A Rails? Nezesložiťují, co jednoduché je. Weby z principu jednoduché jsou; i složitější dynamické stránky lze považovat za guestbook trochu jinak. Na první pohled by se mohlo zdát, že Rails v porovnání s PHP nepřinášejí nic nového. Žádný převratný šablonovací systém, ani kontinuace, ani absolutní oddělení logiky od obsahu (což není úplně pravda, ale o tom později). Proč jsou tedy stále populárnější?
Chci vědět proč…
Nejprve – proč jsem se pustil do seriálu?
Abych Rails přiblížil lidem, kteří třeba pracují s PHP a chtěli by zkusit alternativu. Nechci psát o Rails pro programátory Rails, dokumentace je na webu dost. Přesto na webu chybí úplný základ, z něhož by si člověk udělal prvotní představu.
Tvůrci s oblibou píší, jak je s Rails vývoj webů extrémně rychlý, snadný a vůbec extrémně extrémní. Demonstrace poněkud zavánějí PR, ostatně podívejte se na video (mov, 50 MB). Mám trochu odlišné zkušenosti. PR vyznívají skoro tak, že z vás za čtyři dny učiní guru, jenže stále platí zákon Sebe neurychlíš. Rails umějí daleko víc, než dávají na první pohled znát; jsou komplexním systémem řešícím například i různé stupně kešování. Naštěstí je můžu používat, přestože zdaleka neobsáhnu ani 50 % jejich funkcionality. A to, myslím, svědčí o dobrém systémovém návrhu.
Od seriálu čekejte polopatické řešení běžných úloh, jako je guestbook, stránkování, galerie s uploadem fotografií a generováním náhledů, lokalizace, přihlašování či nyní módní AJAX. A nemusíte být zkušení v jazyce Ruby (to přijde samo).
Proč Ruby?
Framework mohl být napsán klidně v čemkoli jiném, avšak autor zvolil Ruby díky přizpůsobitelnosti tohoto jazyka. O Ruby mimochodem existuje mnoho (1 2 3 4 5) zajímavých článků a seriálů. (Nebudu se tu rozepisovat o dalších výhodách Ruby, protože vyplynou z flamewar.)
Ke konkrétním řešením se dostaneme v následujících dílech. V tomto dílu se pouze pokusím objasnit základní filozofii, která Rails provází, a snad vám i odpovědět na otázku, proč jsou Rails stále populárnější.
Filozofie
MVC (Model, View, Controller)
<div><?include('a.inc');
if($prom=='reklama' || $prom=='reklama2' || $prom=='reklama3'){
$sq=mysql_query('select * from tbl_reklama where nazev LIKE "$prom_%"');
if ($sq) {
?><table cellspacing=0 cellpadding=0><?
while($r=mysql_fetch_row($sq)) {
echo "<tr>"; echo "<td>nazev: ".$r['nazev'];
echo "<td>cena: ".$r['cena']; echo "</tr>"
}
?></table><?
}
?>
</div>
Zdá se vám tento kus PHP povědomý? Vzhledem k množství podobných kódů na Internetu občas uvažuji, že bych je začal prodávat na kila, dokonce bych přitom ani neodporoval GNU/GPL. Vada tohoto programovacího stylu spočívá v mixování programového kódu (PHP) a zobrazovaného obsahu (html). Naštěstí existuje lehké řešení – skript můžeme rozdělit do dvou souborů. V prvním souboru data „uvařit“ a pomocí druhého, šablony, hotová data zobrazit. Říká se tomu oddělení logiky od obsahu.
Jelikož je nutné některé bloky html kódu opakovat či je zobrazovat pouze v určitých případech, musí šablona obsahovat i řídicí kód. Bez „ifů“ a „foreachů“ se v ní neobejdeme. Lze pak ale tvrdit, že oddělujeme logiku od obsahu? Některým lidem PHP foreache a ify v šabloně natolik vadily, že vytvořili vlastní šablonovací jazyk odlišný od PHP, který umí, světe div se, ify a foreache (viz Smarty).
Otázku je nutné položit jinak: Dá se šablona obsahující ify a foreache nazývat odděleným obsahem? Rails pragmaticky říkají Ano. Fakt, že šablona obsahuje ify, foreache a jednoduchá volání metod ještě neznamená, že obsahuje logiku. Řekněme, že obsahuje zobrazovací logiku, nikoli však funkční logiku. A to je dostatečné oddělení, nebo snad ne?
Přestože existují frameworky znající způsob, kterak logiku z šablony odstranit úplně (obvykle se přesune do dalšího souboru), větší čitelnosti ani snazší editovatelnosti už tím obvykle nedocilují.
Pohled (View)
Na základě předchozího odstavce můžeme PHP směle považovat za šablonovací systém. K čemu tedy používat Rails a nezůstat u PHP? Rails nejsou jen šablonovací systém. Šablonovací systém je v Rails, řekl bych, to nejméně podstatné.
Část, která se stará o šablony, se nazývá pohled (View). Defaultně je použit ERB renderer neboli šablonovací systém á la PHP. Soubory mají koncovku .rhtml a obsahují html prokládané značkami <%= ‚s Ruby kódem uvnitř‘ %>.
Kromě ifů a foreachů se uvnitř značek vyskytují pomocné metody, takzvané helpers. Pomáhají generovat html. Například metoda check_box vygeneruje checkbox, ale nejen to – umí ho vygenerovat i zaškrtnutý. Podobně text_field vytváří textové pole a zároveň ho dokáže naplnit textem. Díky tomu snadno vytvoříme formulář, který se po odeslání objeví předvyplněný znovu, třebas kvůli chybějícím údajům. Pozor, pomocné metody data už jenom zobrazují, nevytvářejí je. Způsob, jakým se data vytvoří, jinými slovy logiku programu, popíšu za chvíli.
Abych pravdu řekl, na tyto pomocníky budete zpočátku nadávat a považovat je spíš za pana Sponku. Trvalo mi docela dlouho, než jsem si zvykl a nejběžnější helpery si osvojil (teď už vidím, že pořadí parametrů metod je víceméně intuitivní).
Podotýkám, že k ERB existuje i alternativa – Kwartz, která zcela odděluje obsah od logiky. Chcete-li pro Rails napsat vlastní renderer, je to možné. ERB v nich není „zadrátováno“.
Kontrolér (Controller)
Kontrolér řeší logiku. V podstatě řídí posloupnost zobrazování stránek a výměnu dat mezi nimi. (Jak bylo řečeno, o generování html se stará pohled (view), kontrolér pouze určí, který pohled bude použit.)
Oproti klasickému způsobu programování stylem „co akce, to soubor“, jak ho známe z PHP, ovládá kontrolér více akcí najednou. Co je kontrolér konkrétně? Soubor obsahující jednu třídu s metodami, jejichž názvy odpovídají názvům akcí. Rails patřičnou metodu zavolají, v ní se data „uvaří“, a pokud nebude výslovně určen jiný pohled, použijí stejnojmenný pohled, jako je jméno akce.
V kontroléru je možné pracovat se session, přesměrovávat, kombinovat akce, měnit výstupní pohledy, layout, opatřit některé akce loginem atd. S kontroléry a akcemi je navíc spjata url mapa (routes), která mapuje url na jednotlivé kontroléry a akce. Týž kontrolér-akce může být díky mapě dosažitelný ze dvou url, například
http://www.casopis.cz/2005/10/nazev_clanku
nebo
http://www.casopis.cz/clanky/nazev_clanku
Zbývá vysvětlit, co je to…
Model
Programovou logiku Rails ještě více rozdělují, a to mezi kontrolér a model. V kontroléru se nesetkáme s mnohořádkovými metodami či sql dotazy, kontrolér pouze řídí posloupnost zobrazování stránek a měl by být maximálně jednoduchý. Model je to, co se stará o nízkoúrovňové získávání dat. Tvoří rozhraní mezi kontrolérem a databází, navíc řeší vztahy mezi ostatními modely a může být sdílen více kontroléry.
Nenapsal jsem důležitou věc: S databází Rails pracují objektově. Díky ActiveRecord jsou sql tabulky převedeny na třídy. Pomocí metod těchto tříd pracujeme s tabulkami, instance pak odpovídají řádkům tabulek. Uvedu příklad vytvoření nového záznamu v knize hostů pomocí modelu Guestbook:
gb = Guestbook.new
gb.nick = 'MiG'
gb.message = 'dneska zase nestíhám, už musím letět'
gb.save
Vylistování všech záznamů provedeme takto:
list = Guestbook.find_all
list.each { |gb|
puts "Od: #{gb.nick}"
puts "Zpráva: #{gb.message}"
}
Sql tabulka v tomto případě nejspíš sestává ze tří sloupců, id, nick a message.
Jestliže chceme získávat specifická data, přidáme patřičné metody se sql dotazy do modelu. Například „ Guestbook.find_all_with_photos
“ vracející všechny uživatele s fotografií.
Další základní filozofii Rails je…
DRY (Don't Repeat Yourself)
Navrhuji dát si pauzu, ale konec už se blíží.
Ačkoli je opakování matkou moudrosti, příliš časté opakování vede ke zblbnutí. Aby bylo programování i nadále zábavou (teorie!), Rails definují jednu věc pouze na jednom místě, čímž nám šetří prsty. Abychom se ještě méně upsali,
žádná konfigurace není v XML
XML považuji za výborný formát výměny dat, ale co se týče vhodnosti pro editaci lidskou rukou, existují lepší formáty. Ve světě Ruby, a tudíž i v Rails, se hojně používá formát YAML, jenž připomíná spíše běžný strukturovaný text. Práce s ním je snadná i pro programátory, neboť pokrývá známé datové typy (pole, asociovaná pole, čísla, stringy a další), takže jeho načtením získáme přímo objekt tak, jak byl do yaml serializován.
bylo zvoleno Ruby – neukecaný jazyk
Volání metody lze v Ruby zapsat jak se závorkami a středníky, tak i bez, Ruby rozumí dost divným konstrukcím. Běžně závorky používám kvůli přehlednosti, ale v ERB šabloně „holé“ pomocné metody nevadí, posuďte sami:
<%= checkbox( 'check1', { :checked => true, :size => 12 } ); %>
<%= checkbox 'check1', :checked => true, :size => 12 %>
helpers (pomocné metody)
Už jsem je popsal; umějí prvky formulářů nejen generovat, ale zároveň i plnit, takže nemusíme psát kód pro zakliknutí checkboxu.
scaffolding a generátory
Na závěr tohoto dílu chci zmínít jeden z nejmocnějších nástrojů. Jsou jím generátory, zejména scaffold generátor. K čemu slouží? Abyste nemuseli psát všechno ručně, předgenerují základní strukturu automaticky. Například scaffold generátor:
$ script/generate scaffold guestbook
Máme-li tabulku, obvykle ji potřebujeme vylistovat, vkládat nové řádky, upravovat je či je mazat. Tímto jednoduchým příkazem generátor vyrobí celou webovou aplikaci na editaci tabulky. Stačí zadat url do prohlížeče a můžeme tabulku plnit.
Jenže… výsledek přeci nebude v grafice, jakou očekáváme?! Ovšemže ne. Je to prototypování webů, které se díky scaffoldingu stává rychlejší a pohodlnější. Osobně začínám vygenerováním kostry, naplním základní data do tabulek, a teprve poté dolaďuji detaily. Už v prototypu se třeba ukáže, že něco půjde řešit úplně jinak.
Za velký přínos scaffold generátoru pokládám předgenerování formulářů. Scaffold automaticky vyrobí prvky formuláře podle sloupců v sql tabulce, takže z VARCHARu se stane text input, z TEXTu textarea, z BOOLEANu checkbox atd.
Kromě scaffold generátoru existují generátory loginu, lokalizace, web service atd., jejichž použití je obdobné. Některé generátory jsou obsaženy přímo v Rails, ostatní lze stáhnout z webu.
Závěr
Kromě výše zmíněných DRY (nebudu se opakovat), které podstatně urychlují vývoj aplikace, můžete od Rails očekávat větší přehlednost celé struktury aplikace. Komukoli, kdo pracuje s Rails, bude záhy jasné, jak co funguje a kde se co nachází.
V následujícím dílu vytvoříme první aplikaci a ukážeme si možnosti scaffoldingu a debugování.