Intro
Kartu su web2 banga atėjo SE[O|F] (Search Engine Optimization/Friendly) ir kalba pakrypo apie gražius URL, kuriuos lengviau įsiminti tiek žmogui, tiek paieškos varikliui. Apie tokius gražius URL aš pirmą kartą sužinojau iš straipsnio php.lt svetainėje. Tiesa, tada aš dar nelabai supratau, kam tokie dalykai reikalingi, kaip veikia paieškos varikliai ir pan. Kelių dalykų aš dar dabar net nežinau, tačiau senstant blogėja atmintis, tad aš tikrai negaliu pasakyti kuriuo id ir sub_id yra pasiekiami tam tikri puslapiai kokiame nors domene. Štai čia ir atėjo į pagalbą SEF URL’ai.

Aišku, gali kilti klausimas - kam reikalingas RoR karkase, jei visa tai galima padaryti pačiame http serveryje (kad ir su mod_rewrite, pavyzdžiui). Atsakymas yra labai paprastas - tam, kad praplėstų RoR panaudojimo galimybes, juk ne visi http serveriai sugeba “perrašinėti” URL’us, būtent todėl šitas dalykas buvo perkeltas į patį RoR karkasą. Man asmeniškai, RoR karkaso yra žymiai mielesnis užsiėmimas, negu mod_rewrite-voodoo magija .)
RoR karkase visą maršrutizavimą galima sukonfigūruoti viename faile: /config/routes.rb (ganėtinai nuspėjama, ar ne?). Šiame faile pagal nutylėjimą yra naudojami du keliai, kurių pačioje pradžioje, darant paprastas aplikacijas, gali pilnai užtekti. Tačiau kiek web aplikacijų - tiek ir skirtingų kelių.

Teorija

Pradžiai - truputis sutartinės teorijos šiam postui:

  • maršrutas - taisyklė, pagal kurią tam tikras URL yra susiejamas su kontrolerio metodu bei metodo parametrais;
  • - veiksmas, kurio metu yra valdomi maršrutai;
  • susieti maršrutai - taisyklės, turinčios joms priskirtus vardus;

Maršrutizavimo API

Šiaip dokumentacijoje šios RoR karkaso dalies yra labai mažai. Kaip patys vėliau pamatysite - jos nelabai daug ir reikia. naudoja vos kelis metodus, kurie turi po kelis parametrus, tačiau tokiame siaurame pasirinkime slypi labai daug galimybių.

Pačiame routes.rb faile matyti, kad viskas yra manipuliuojama per ActionController::Routing::Routes.draw. Šiaip ActionController::Routing::Routes pagal wiki dokumentacija yra tiesiog RouteSet instancija, bet ne pati klasė. Būtent RouteSet.draw metodas ir daro visą maršrutizavimą. Dar RouteSet turi kelis metodus, kurie ir yra skirti būtent nurodyti, keisti ar pridėti maršrutus RoR aplikacijai:

  • connect - prideda maršrutą prie maršrutų masyvo. Naudojami argumentai yra perduodami į Route.initialize. Šie argumentai yra:
    • kelias (path) - URL arba kelias, kuriam reikėtų taikyti taisyklę;
    • parinktys (options) - asociatyvus masyvas (hash) nurodantis, ką reikėtų daryti su pateiktu keliu;
  • reload - išvalo visus paskirtus maršrutus ir pakrauna routes.rb bylą iš naujo. Šitas metodas nenaudoja jokių argumentų ir šiaip jį lengviau yra kviesti per Action::Controller::Routes.reload;
  • named_route - prideda susietą maršrutą nurodytu vardu. Naudojamas tada, kai jūsų maršruto pavadinimas kertasi su esančiu RouteSet metodu (pvz connect ar reload). Naudojimas panašus į connect metodo, tik prisideda vienas papildomas parametras - maršruto vardas, taigi argumentų seka yra ši:
    • vardas - maršrutui priskirtas vardas;
    • kelias (path) - tas pats kaip ir connect metode;
    • parinktys (options) - tas pats kaip ir connect metode;
  • (susietas maršrutas) - jeigu jūs kviesite neapibrėžtą metodą, tada RouteSet iškvies metodą named_route su neegzistuojančio metodo pavadinimu, kaip pirmu argumentu bei kelio ir parinkčių argumentais kaip connect metode*;

* Daugiau informacijos apie susietus maršrutus yra RoR karkaso wiki. Šiaip nepatarčiau jų naudoti iki tol, kol neperkandote esminių maršrutizavimo principų.

Kelio parametras yra papraščiausia simbolių eilutė (string), kuri yra apdorojama sekančiai:

  • eilutė yra padalinama į atskiras dalis, atskiriant per įžambųjį brūkšnį (’/');
  • dalys, kurios turi pavidalą :dalis, asociatyviame parametrų masyve bus priskirti atitinkamiems masyvo elementams (pvz params[:dalis]). Žodis :controller yra traktuojamas ypatingai (žiūrėti žemiau);
  • Eilutės dalis :controller pavidalu gali atspindėti ne tik kontrolerį, bet ir tam tikrą modulį. Pvz Admin::NewsController modulis gali būti pasiektas :controller daliai priskyrus ‘admin/news‘ reikšmę. Atkreipkite dėmesį į kapitalizaciją, tad ManoGerasModulis::ManoDarGeresnisKontroleris bus atpažinti kaip ‘mano_geras_modulis/mano_dar_geresnis_kontroleris’;
  • Jeigu yra dalių, kurios atrodo kaip *dalis (jokio tarpo tarp žvaigždutės ir žodžio), tai ši dalis panaikins visas po to einančias eilutės dalis. Tokia dalis privalo būti paskutinė kelio dalis. Likusios dalys bus priskirtos į params[:dalis] masyvą. Pvz:
    • Kelio eilutės šablonas: ‘kelias/:iki/*kazko/labai/faino‘;
    • Užklausiamas URL: ‘kelias/pas/jona‘;
    • Atitinkamas params masyvas: params[:iki] => ‘pas’, params[:kazko][0] => ‘labai’, params[:kazko][1] => ‘faino’;
  • Kitos dalys, kuriose nėra nei * nei : simbolių yra traktuojamos taip kaip užrašytos ir turi tiksliai atitikti užklausiamą URL’ą;

Parinkčių parametras yra paprasčiausias asociatyvus masyvas (hash), kuris turi paprasčiausias raktų/reikšmių poras:

  • :defaults => hešas - laiko pagrindines reikšmes maršrutui. Pvz.: :defaults => { :action => ‘index’ }. Pats RoR karkasas stengiasi intuityviai parinkti reikšmes pagal nutylėjimą. Pvz., nenurodžius :action parametro kelyje pagal nutylėjimą yra imama ‘index‘ reikšmė. Atitinkamas pavyzdys galėtų būti toks:
    • map.connect ‘news/:id/:action/’, :defaults => { :action => ‘read’ }, :controller => ‘news’;
    • Kreipimasis: http://demo.ror.app.com/news/2
    • Atitinkamas maršrutas: :controller => ‘news’, :action => ‘read’;
  • :requirements => hešas - tai nėra paprastų reikšmių hešas. Vietoje to atitinkamiems maršruto parametrams yra nurodomos įprastinės išraiškos (regexp), kurias turi atitikti šie parametrai. Pvz.:
    • map.connect ‘news/:id’, :controller => ‘news’, :action => ‘read’, :requirements { :id => /\d+/}
    • Kreipimasis: http://demo.ror.app.com/news/asdf
    • Atitinkamas maršrutas šio URL’o neatitiks, kadangi eilutės dalis po ‘news’ nesusidaro iš skaitmenų;
  • :raktas => reikšmė - raktai, kurie nėra rezervuoti bus sudėti į params masyvą (params[:raktas]);
  • :raktas => įprastinė_išraiška - nurodo įprastinę išraišą duotam parametrui iš :requirements hešo;

Tiesa aš žinau, kad jums iš tų kelių kol kas atrodo yra per mažai naudos, bet vėliau pamatysite, kad jie gali būti labai reikalingi.

Susieti keliai

Pagal API dokumentaciją galima lengvai sukurti vardinius kelius. Užtenka vietoje map.connect parašyti map.vardinis_kelias ir nurodyti vieną parametrą. Pvz.:

map.naujiena_numeris_du :controller => ‘news’, :action => ‘read’, :id => 2

Dabar kreipiantis adresu http://demo.ror.app.com/naujiena_numeris_du bus kviečiamas ‘news‘ kontrolerio ‘read‘ metodas, kuriam bus paduodamas argumentas ‘2′.

Praktika

Kol kas (išskyrus SEF URL) maršrutizacija nedavė daugiau naudos (kad ir kiek jos užtektinai atrodytų). Maršrutizacija dar labai padeda kontroleriuose bei vaizduose. Ši nauda pasirodo naudojant kelis metodus:

  • link_to - naudojamas vaizduose norint gauti kelią iki kito kontrolerio/metodo/parametro, kito kontrolerio ar kito metodo. Šis metodas turi daug “atmainų” (link_to_if, link_to_image, link_to_unless bei link_to_unless_current), kurios sukonkretina naudojimą priklausomai nuo situacijos, tačiau pagrindinis naudojimas yra sekantis:
    • link_to ‘Nuorodos tekstas’, :controller => ‘kontroleris’, :action => ‘metodas’, :id => 5 - tokia metodo forma yra naudojama, kai norima išgauti nuorodą į kito kontrolerio metodą su atitinkamais parametrais;
    • link_to ‘Nuorodos tekstas’, :controller => ‘kontroleris - kviečiant metodą taip yra sukuriama nuoroda į nurodytą kontrolerį, o vietoje metodo bus naudojamas metodas pagal nutylėjimą (’index’);
    • link_to ‘Nuorods tekstas’, :action => ‘veiksmas’ - šiuo atveju sukonstruota nuoroda bus į to pačio kontrolerio kitą metodą;
  • url_for - grąžiną URL pagal nurodytus parametrus, kurie pateikiami taip pat kaip ir link_to metodui. Grąžinamas URL yra be domeno dalies, tad vietoje demo.ror.app.com/controller/action/id gausite tik /controller/action/id;
  • redirect_to - taip, man, kaip php programuotojui, tai primena header(’Location…’);. Metodo parametrai yra tokie patys, kaip ir pirmiems dviems metodams. Išimtis atsiranda tada, kai norima nukreipti vartotoją į susietą kelią. Tokiu atveju yra naudojama ši sintaksė:
    • redirect_to susietas_kelias_url - (būtinai turi būti postfiksas ‘_url’);

Praktikoje gaunant URL’us kontroleriams bei metodams yra truputis magijos. Jeigu jūs savo routes.rb faile nurodysite sekantį maršrutą:

map.latest_news ”, :controller => ‘news’, :action => ‘latest’

ir norėdami padaryti nuorodą kokiame nors vaizde į būtent šį puslapį jūs žinoma parašysite:

link_to ‘Vėliausios naujienos’, :controller => ‘news’, :action => ‘latest’

tada kontrolerio sugeneruotame vaizdo html kode bus nuoroda ne į demo.ror.app.com/news/latest, bet tiesiog į demo.ror.app.com/ mat RoR karkasas prieš sugeneruodamas nuorodą patikrina ar nėra maršrutų būtent pateiktam kontroleriui bei metodui, kas salygotų “trumpesnio kelio” pateikimą. Tokia pati magija yra ir url_for bei redirect_to metoduose.

Tikiuosi šis straipsnis suteiks jums bendrą supratimą apie tai, kaip RoR karkase vyksta maršrutizacija. Aš ieškosiu dar informacijos apie RoR maršrutizavimą ir po kurio laiko tikiuosi apšviesti jus su kokiais nors advanced maršrutizavimo triukais.

Komentarai ir originalus straipsnis: http://blog.rubyonrails.lt/marsrutizavimas-routing.html

Panašūs straipsniai


“Maršrutizavimas (Routing)” komentarų: 1

  1. bigzel

    Tikrai geras straipsnis, atsizvelgiant i tai kad apie rails’u routinga yra labai mazai info. Malodec enc!