Framework Ruby on Rails: Rozdiel medzi revíziami

Z Kiwiki
Skočit na navigaci Skočit na vyhledávání
d (Zamyká „Framework Ruby on Rails“ ([edit=sysop] (na neurčito) [move=sysop] (na neurčito)))
 
(7 medziľahlých úprav od 2 ďalších používateľov nie je zobrazených)
Riadok 2: Riadok 2:
 
[[Kategória:Informatika]]
 
[[Kategória:Informatika]]
 
[[Kategória:Skriptovacie jazyky]]
 
[[Kategória:Skriptovacie jazyky]]
 
+
<H1_CSS chapter="4" prefix="Kapitola" />
{{Hlavička_FM|Pokročilé vlastnosti skiptovacích jazykov|Ivana Zuzinová|Ing. Juraj Ďuďák|
 
2008/2009
 
|Bakalárska práca
 
|Mechatronika
 
}}
 
 
<div class="sideBox">
 
<div class="sideBox">
 
{| class="" border=0 cellpadding=5
 
{| class="" border=0 cellpadding=5
Riadok 16: Riadok 11:
 
|-
 
|-
 
| 2.
 
| 2.
| [[Pokročilé vlastnosti skiptovacích jazykov_2| Ruby]]
+
| [[Jazyk Ruby]]
 
|-
 
|-
 
| 3.
 
| 3.
| [[Pokročilé vlastnosti skiptovacích jazykov_3|Porovnanie Ruby a PHP]]
+
| [[Porovnanie Ruby a PHP]]
 
|-
 
|-
 
| 4
 
| 4
| [[Pokročilé vlastnosti skiptovacích jazykov_4|Ruby on Rails]]
+
| [[Framework Ruby on Rails]]
 
|-
 
|-
 
| 5
 
| 5
| [[Pokročilé vlastnosti skiptovacích jazykov_5|Praktická aplikácia využívajúca Rails ]]
+
| [[Praktická aplikácia využívajúca framework Rails]]
 
 
|-
 
| 6
 
| [[Pokročilé vlastnosti skiptovacích jazykov_6|Záver]]
 
 
|}
 
|}
 
</div>
 
</div>
----
+
__TOC__
=Ruby on Rails=
+
V predchádzajúcej kapitole boli zhrnuté základné informácie o písaní kódu v jazyku Ruby, ktorý je základom MVC frameworku Ruby on Rails. V nasledujúcej časti popíšeme architekrúru Rails, pričom sa bližšie zameriame na schopnosť Rails efektívne pracovať s databázami.
V predchádzajúcej kapitole boli zhrnuté základné informácie o písaní kódu v jazyku Ruby, ktorý je základom MVC frameworku Ruby on Rails. V nasledujúcej časti popíšeme architekrúru Rails, pričom sa bližšie zameriame na schopnosť Rails efektívne pracovať s databázami.==
+
 
 
==MVC architektúra==
 
==MVC architektúra==
 
MVC architektúra (model-view-controller), ako už bolo spomínané v úvode, nie je používaná a jedinečná iba pre Rails, dokonca existovala ešte pred Ruby a Rails. Napriek tomu, Rails plne prevzal myšlienku oddelenia aplikačných dát, užívateľského rozhrania a riadiacej logiky a dal jej nový rozmer.
 
MVC architektúra (model-view-controller), ako už bolo spomínané v úvode, nie je používaná a jedinečná iba pre Rails, dokonca existovala ešte pred Ruby a Rails. Napriek tomu, Rails plne prevzal myšlienku oddelenia aplikačných dát, užívateľského rozhrania a riadiacej logiky a dal jej nový rozmer.
Riadok 424: Riadok 415:
 
Migrácie sú súbory popisujúce zmenu v databázovom systéme (vrátane vytvorenia novej tabuľky). Z technického hľadiska sú migrácie triedy nachádzajúce sa v adresári db/migrate aplikácie Rails, Všetky migrácie sú potomkami triedy ActiveRecord::Migration, ktorej metódy používajú. Každá migrácia musí obsahovať metódy tredy up a down. Metóda up sa volá v prípade migrácie z nižšej verzie (popr. žiadnej) na vyššiu. Metóda down sa používa pri návrate k predošlej (staršej) verzii. Migrácie sa obvykle spúšťajú pomocou príkazu rake db:migrate. Trieda zabezpečujúca migrácie funguje tak, že porovná verziu databázy uloženú v tabuľke schema_info a číslo poslednej migrácie v adresári db/migrate a pokiaľ nájde migrácie s číslom väčším ako je číslo databázy, tak tieto migrácie postupne spúšťa. Príkladom môžu byť migrácie z praktickej úlohy, ktorú budeme riešiť v nasledujúcej kapitole – pozri obrázok:
 
Migrácie sú súbory popisujúce zmenu v databázovom systéme (vrátane vytvorenia novej tabuľky). Z technického hľadiska sú migrácie triedy nachádzajúce sa v adresári db/migrate aplikácie Rails, Všetky migrácie sú potomkami triedy ActiveRecord::Migration, ktorej metódy používajú. Každá migrácia musí obsahovať metódy tredy up a down. Metóda up sa volá v prípade migrácie z nižšej verzie (popr. žiadnej) na vyššiu. Metóda down sa používa pri návrate k predošlej (staršej) verzii. Migrácie sa obvykle spúšťajú pomocou príkazu rake db:migrate. Trieda zabezpečujúca migrácie funguje tak, že porovná verziu databázy uloženú v tabuľke schema_info a číslo poslednej migrácie v adresári db/migrate a pokiaľ nájde migrácie s číslom väčším ako je číslo databázy, tak tieto migrácie postupne spúšťa. Príkladom môžu byť migrácie z praktickej úlohy, ktorú budeme riešiť v nasledujúcej kapitole – pozri obrázok:
  
[[Súbor:pvsj4.8|frame|none|Obrázok 4.8.: Zobrazenie migrácií projektu rozvrh v prostredí NetBeans]]
+
[[Súbor:pvsj4.8.png|frame|none|Obrázok 4.8.: Zobrazenie migrácií projektu rozvrh v prostredí NetBeans]]
  
 
Pre správnu funkčnosť migrácií je potrebné splniť dve podmienky:
 
Pre správnu funkčnosť migrácií je potrebné splniť dve podmienky:

Aktuálna revízia z 21:54, 20. január 2010


V predchádzajúcej kapitole boli zhrnuté základné informácie o písaní kódu v jazyku Ruby, ktorý je základom MVC frameworku Ruby on Rails. V nasledujúcej časti popíšeme architekrúru Rails, pričom sa bližšie zameriame na schopnosť Rails efektívne pracovať s databázami.

MVC architektúra

MVC architektúra (model-view-controller), ako už bolo spomínané v úvode, nie je používaná a jedinečná iba pre Rails, dokonca existovala ešte pred Ruby a Rails. Napriek tomu, Rails plne prevzal myšlienku oddelenia aplikačných dát, užívateľského rozhrania a riadiacej logiky a dal jej nový rozmer. MVC je predlohou pre architektúru softwarových aplikácií – rozdeľuje aplikáciu na nasledovné tri komponenty:

  • Models – modely – určené na spracovávanie dát a prístup k databázam
  • Views – pohľady – spracovávajú objekty grafického užívateľského rozhrania a vykonávajú prezentačnú logiku
  • Controllers – kontroléry – riadia užívateľské rozhranie a vykonávajú aplikačnú logiku

Výsledný priebeh spracovania užívateľskej požiadavky je znázornený na obrázku 4.1:

Obrázok 4.1.: Spracovanie požadavky v architektúre MVC

  1. Prehliadač na strane klienta zasiela požiadavku kontroléru prostredníctvom stránky na servri.
  2. Kontrolér obnovuje potrebné dáta od modelu za účelom vykonať požiadavku.
  3. Model komunikuje s databázou a získava alebo ukladá potrbné dáta.
  4. Kontrolér posúva získané a spracované dáta pohľadu.
  5. Vygeneruje sa pohľad a zasiela sa späť prehliadaču na zobrazenie.

Rozčlenenie softwarových aplikácií na tieto 3 rôzne komponenty je vhodným riešením z mnohých dôvodov, vrátane nasledujúcich:

  • zlepšuje sa rozšíriteľnosť – schopnosť aplikácie rozrastať sa
  • zjednodušuje sa údržba – zmeny jedného komponentu neovplyvnia ostatné
  • podporuje sa opätovné použitie – jeden model môže byť použitý v mnohých pohľadoch a naopak

MVC v Rails

Ištalácia Rails

Rails v prostredí Windows nainštalujeme zadaním príkazov do príkazového riadku:

gem install rails –include-dependencies  
gem update rails

K fungovaniu Rails potrebujeme ešte databázu (my sme použili MySQL) a web server. Rails obsahuje jednoduchý web server WEBRick, ktorý môžeme spustiť príkazom

ruby script/server 

Uprednostňovaňejším serverom je Mongrel, Rails ale môže bežať aj na serveroch Apache (so zabudovanými modulmi pre Rails) alebo Lighttpd.

Obrázok 4.2.: Podadresár app

Rails podporuje koncept modelov, pohľadov a kontrolérov, ktoré sú vzájomne oddelené a kód každého z týchto elementov je uložený ako samostatný súbor v oddelenom adresári. Pokiaľ by sme sa pozreli do novovytvoreného Rails projektu, tak v priečinku app môžeme nájsť spomínané adresáre:

Ako vidno, každý komponent MVC architektúry má svoje miesto vnútri podpriečinku app – podpriečinok modelov, pohľadov, kontrolérov. Rails implementuje MVC zavedením troch vrstiev (komponentov) medzi časti frameworku. Sú to:

  • Active Record – modul zabezpečujúci funkcie modelu – každý model dedí vlastnosti tejto triedy.
  • Action View – komponent, ktorý ma na starosti prezentáciu stránok navracajúcich sa klientovi. Pohľady dedia vlastnosti tejto triedy.
  • Action Controller – modul spracovávajúci požiadavky klienta, zabezpečujúci komunikáciu medzi modelom a pohľadmi. Kontroléry dedia vlastnosti triedy Action Controller.

Action Controller a Action View sa spoločne nazývajú aj Action Pack.

Active Record (Model)

Active Record je navrhnutý pre správu všetkých aplikačných požiadaviek súvisiacich s databázou, zahŕňajúc:

  • zabezpečenie spojenia s databázou – Active Record je schopný prostrednictvom špeciálneho adaptéru vytvoriť prepojenie s databázami MySQL, SQLite, PostgreSQL alebo Oracle, DB2, Microsoft SQL Server a i.. Vďaka tomu sú dve odlišné prostredia ako objektovo orietované programovanie v Ruby a neobjektový jazyk SQL schopné prepojenia.
  • vyberanie potrebných dát z tabuliek
  • ukladanie nových dát do databázy

Okrem toho je Active Record ORM framework – Object Relational Mapping framework. To znamená, že každá tabuľka je zaradená do určitej triedy, riadky tabuliek sú zaradené medzi objekty a stĺpce tabuľky sú atribúty objektov. Tabuľke je možné priradiť triedu nasledovne:

class User < ActiveRecord::Base
end

Týmto sa vytvorí trieda User. Časť < ActiveRecord::Base zabezpečuje, že trieda User je podtriedou Active Record a dedí jej funkcie. Názov triedy má byť totožný s názvom tabuľky, pričom názov triedy (model) je v jednotnom čísle a názov tabuľky v množnom čísle. Tento spôsob pomenovávania patrí medzi konvencie Rails a stará sa o to, aby Active Record vedel automaticky priradiť správnu tabuľku k vytvorenej triede. Modely sú ukladané do priečinku app/models. Príklad pomenovania tabuliek a tried je v tabuľke 4.1.:

Tabuľka 4.1.: Konvencie pomenovania tabuliek a tried v Rails
Tabuľka Trieda
users
events
people
user_event
User
Event
Person
UserEvents

Druhou významnou konvenciou je, že tabuľky obsahujú identifikačný stĺpec id. Každá tabuľka má tento unikátny stĺpec pomenovaný id, ktorý sa vytvorí automaticky pri generovaní tabuľky. Tento stĺpec môže byť primárnym kľúčom tabuľky (hodnota použitá na unikátnu identifikáciu riadku tabuľky). Ďalšie funkcie modelu budú rozobraté komplexnejšie v nasledujúcej časti.

Action Controller (Controller)

Kontrolér funguje ako prvok MVC architektúry, ktorý je prepojovacím článkom medzi dátami aplikácie, prezentačnou vrstvou a prehliadačom. Dohliada na množstvo funkcií:

  • rozhodovanie akým spôsobom vybaviť požiadavku prehliadača (napríklad či načíta celý nový obsah pohľadu alebo len jeho časť)
  • obnovovanie požadovaných dát z modelu a ich následné odoslanie pohľadu
  • zhromažďovanie informácií z požiadavky prehliadača a ich následné použitie na vytvorenie alebo obnovenie dát v modeli

Každý kontrolér je podtriedou, ktorá dedí vlastnosti od triedy Action Controller, ale vlastní aj samostatné špecifické funkcie. Tieto sa môžu definovať sami ako metódy triedy, vpísaním do súboru kontroléru. Príklad:

class UsersController < ActionController::Base
	def index
	end
	def show
	end
end

Vytvorili sme jednoduchú definíciu kontroléru UsersController s dvomi prázdnymi metódami index a show. Každý kontrolér je uložený v samostatnom Ruby súbore s príponou .rb v adresári app/controllers. UsersController bude teda uložený ako app/controllers/users_controller.rb. Ako vidno, v Rails existujú aj konvencie pri pomenovávaní tried a súborov kontrolérov:

  • mená tried sú písané vo forme MyAllUsersController – každé slovo začína veľkým písmenom, bez medzier medzi nimi
  • mená súborov sú písané malými písmenami, oddelené podčiarkovníkom – my_all_users_controller.rb

Tieto konvencie nie sú nevyhnutné, v prípade ich nedodržania však Rails zaberie množstvo času lokalizovať potrebný súbor a zvolený názov je nutné nakonfigurovať do aplikáce ručne. Našťastie, väčšinou nie je potrebné pomenovávať súbory a triedy manuálne, Rails ich automaticky pomenuje podľa zadaných konvencií a uloží ich do adresára app/controllers.

Action View (View)

Ako bolo spomenuté, pohľady by mali obsahovať iba prezentačnú logiku, zabezpečovať grafické užívateľské rozhranie. Sem spadajú úlohy spojené so zobrazovaním stránok v aplikáciách – kód v pohľadoch by nemal obsahovať žiadne zložité operačné úkony, ukladanie alebo získavanie dát z databázy. Všetky pohľady sú uložené v adresári app/views našej alikácie. V pohľadoch sa nachádza takisto akýkoľvek použitý kód HTML. Pohľad nemusí obsahovať principiálne žiadny kód Ruby – môže sa stať, že niektoré pohľady budú obsahovať iba čistý HTML kód. Ruby kód vložený do HTML využíva embedded Ruby syntax – v skratke ERb. ERb je podobný azyku PHP alebo JSP v tom, že využíva možnosť rozloženia kódu medzi kód HTML, oddelením funkčného kódu pomocou značiek – tagov. V PHP to vyzerá nasledovne:

<strong><? echo `PHP Hello world!` ?></strong>

ekvivalent v ERb je:

<strong><%= `Ruby Hello world!` ?></strong>

Poznáme dva rôzne typy párových tagov ERb: jeden obsahujúci znamienko rovnosti =, a druhý, ktorý ho neobsahuje: <%= ... %> - tieto párové značky sa používajú pre regulárny výstup, ktorý bude automaticky zobrazený v prehliadači <% ... %> - značky označujúce kód, ktorý nie je určený na výstup na obrazovku, sem patria rôzne jednoduchšie výpočty, slučky, priradenie premenných - kód nie je zobrazený v pohľade Vytvorenie výstupu na obrazovku prostredníctvom pohľadov je o niečo zložitejšie ako v prípade modelu a kontroléru. Konkretizácia každého pohľadu je zabezpečovaná pomocou modulu Action View, jediný súbor ktorý je potrebné modifikovať je šablóna stránky (template), ktorá obsahuje prezentačný kód pre zobrazenie pohľadu. Tieto súbory sú uložené v priečinku app/views. Takisto tu sa uplatňujú konvencie:

  • počet šablón zodpovedá počtu akcií – metód kontroléru, pričom názov šablóny je totožný s menom akcie kontroléru
  • priečinok v ktorom sú šablóny uložené má názov kontroléru na ktorý sa viažu
  • súbor šablóny obsahuje príponu zloženú z dvoch častí – pozastáva z typu šablóny a jazyka, v ktorom je šablóna písaná. Prípony pohľadov v Rails:

html.erb – štandardná šablóna HTML obsahujúca kód ERb xml.builder – šablóna XML rs.rjs – šablóna, ktorá vracia inštrukcie JavaScript. Tento typ šablóny môže byť použitý napríklad pri modifikácii existujúcej stránky (prostredníctvom Ajax)

Konvencie môžu znieť zložito, avšak v skutočnosti sú pomerne intutívne. Ako príklad uvádzame triedu UsersController, ktorú sme definovali v predošlej časti. Volaním metódy show sa v prípade tohto kontroléru zobrazí šablóna ActionView, ktorá sa nachádza v priečinku app/views/users. Názov šablóny bude edit.html.erb. Rails obsahuje špeciálne šablóny, ako základné schémy (layouts) a čiastkové schémy (partials). Základné schémy sú typy šablón, ktoré obsahujú globálnu vrstvu aplikácie pre daný kontrolér, základnú štruktúru zobrazenia, ktorá je na stránkach nemenná (napríklad hlavné navigačné menu). Čiastkové schémy sú špeciálne podšablóny, ktoré môžu byť použité v aplikácii aj viackrát a sú priradené konkrétnym akciám (metódam) kontrolérov. Komunikácia medzi kontrolérmi a pohľadmi nastáva prostredníctvom premenných inštancií. Upravenie predošlého príkladu nachádzajúceho sa v app/controllers/users_controller.rb:

class UsersController < ActionController::Base
	def index
	    @premenna = `Výpis do pohľadu`
	end
end

V metóde index triedy Users sme definovali premennú inštancií hodnoty string, ktorú je možné vďaka zabudovaným funkciám v ActionView použiť v pohľade app/views/users/index.html.erb nasledovne:

<p>Hodnota @premenna obsahuje text: <%= @premenna %></p>

Práca s databázami v Rails – CRUD

Active Record obsahuje aj funkcie v skratke nazývané ako CRUD – Create, Read, Update, Delete. Rails pojal CRUD ako smer k zjednoušeniu procesu tvorby databazových aplikácií, okrem toho väčšina úkonov spojených s databázami úzko súvisí s CRUD, preto ich spomenieme podrobnejšie.

Create (vytvorenie nového záznamu)

Rails používa na pridanie záznamu do tabuľky nasledovné konštruktory: new – konštruktor, ktorý vytvorí nový objekt triedy a uloží ho do lokálnej premennej. tento objekt je zložený z 2 premenných inštancií:

  • @new_record – typu boolean, dáva informáciu či bol už záznam uložený do tabuľky, pokiaľ áno nastaví sa na 0, v opačnom prípade je 1
  • @attributes – obsahuje hash pozostávajúci z atribútov zvolenej tabuľky, ktoré vytvoril Active Record.

Nový záznam je potrebné následne uložiť metódou save. Príklad:

user = User.new ( :meno 	=> Ján,
	  	      :priezvisko => `Kováč`,
		      :email 	=> kovac@rails.com)
user.save

create – tento konštruktor súčasne vytvorí nový objekt a uloží ho do danej triedy:

User.create ( :meno 		=> Ján,
	     :priezvisko 		=> `Kováč`,
	     :email 		=> kovac@rails.com)

Read (vyhľadávanie záznamov)

Na vyhľadávanie jedného alebo viacerých záznamov v Rails je určená metóda triedy find. Rozoznávame 3 základné spôsoby volania metódy:

  • find(:id) – vyhľadá jeden konkrétny záznam podľa unikátneho čísla id
  • find(:first) – vyhľadá prvý vyhovujúci záznam
  • find(:all) – vyhľadá všetky vyhovujúce záznamy v tabuľke

Za každú metódu je možné ďalej pridať ďalšie voľby, ako napr :order (spôsob zoradenia výstupov) alebo :conditions (podmienky vyhľadávania). Argument :order je synonymom výrazu ORDER v jazyku SQL a argument :conditions má rovnakú funkciu ako SQL výraz WHERE. Príklad použitia vyhľadávania:

>> users = User.find(:all, :conditions => {:meno => `Ján`})
>> users.each {|user| puts user.meno }

Výsledným výpisom bude pole mien užívateľov z tabuľky users, ktorí majú meno Ján. Nasledujúca tabuľka zobrazuje ďalšiu možnosť – dynamické vyhľadávače:

Tabuľka 4.2. : Dynamické vyhľadávače
Vyhľadávač Príklad
find_by_*(cond)
find_all_by_*(cond)
find_by_*_and_*(cond1,cond2)
find_all_by_*_and_*(cond1,cond2)
find_by_meno(`Ján`)
find_all_by_prezvisko(`Kováč`)
find_by_meno_and_priezvisko(`Ján`, `Kováč`)
find_all_by_meno_and_email(`Ján`,`k@rails.com`)

Update (aktualizácia záznamov)

Prepísanie atribútov záznamu najčastejšie vykonávame pomocou metódy update_attributes:

user=User.find(2)
user.update_attributes(:meno => Jozef, :priezvisko => Novák)

Delete (vymazávanie záznamov)

Vymazávanie riadkov tabuľky môže byť vykonané dvoma metódami: destroy a delete. Najčastejšie používaným spôsobom je metóda destroy, ktorá pracuje na úrovni inštancií – teda najprv je definovaný konkrétny záznam na vymazanie, ktorý je potom odstránený. Následné príklady sú ekvivalentné:

user = User.find(1)				
user.destroy

User.find(1).destroy

User.destroy(1)

Výrazy zodpovedajú prekladu do jazyka SQL:

DELETE FROM users WHERE id = 1;

Metódy delete a delete_all patria medzi základné metódy triedy Action Record. Metódy sa voljú priamo v triede, bez vytvorenia objektu, tento je vymazaný okamžite. Metóda delete_all sa najčastejšie používa spolu s podmienkami uvedenými za metódou:

Event.delete([0,1,2,3])
Event.delete_all(id < `4` )

Vzorová aplikácia v Rails

Na základe informácií z predchádzajúcich kapitol vytvoríme ukážku jednoduchej aplikácie Hello world v Rails. Vychádzať pri tom budeme z architektúry MVC, podľa ktorej potrebuje aplikácia model, pohľad a kontrolér. Postup sa skladá z úkonov: 1

Vytvorenie nového projektu – otvoríme si príkazový riadok a presunieme sa na miesto, kde si želáme vytvoriť nový projekt. Následne použijeme príkaz rails a za ním názov projektu:

ruby> cd projekty
projekty> rails test
create
create app/controllers
create app/helpers
...

Rails automaticky vytvorí základnú kostru celej aplikácie s mnohými podpriečinkami – my teraz využijeme hlavne priečinok app a script, ktorý obsahuje mnoho užitočných pomocných skriptov, ako napríklad generátor modelov, kontrolérov a scaffoldov (tvorí model a kontrolér súčasne).

2

Vytvorenie kontroléru – voláme generátor, umiestnený v časti script:

test> ruby script/generate controller Say
...
create app/views/say
create app/controllers/say_controller.rb
...

Rails vygeneruje potrebné súbory, medzi inými kontrolér say_controller.rb a priečinok pohľadov app/views/say

3

Pridanie akcie kontroléru – súbor say_controller.rb vyzerá teraz nasledovne:

class SayController < AplicationController
end

Aby kontrolér vykonával akciu pozdravu, musíme ju zadefinovať ako metódu triedy:

class SayController < AplicationController
	def hello
	end
end

4 Vytvorenie pohľadu – na dokončenie aplikácie je potrebný pohľad akcie hello. Rails automaticky priraďuje akciám tie pohľady, ktoré sa nachádzajú v priečinku s rovnakým názvom ako je názov kontroléru. Preto je potrebné vytvoriť súbor hello.html.erb v priečinku app/views/say. Doňho vložíme základný HTML kód:

<html> 
    <head><title> Hello, Rails! </title></head>
<body>
    <h1> Hello world! <h1>
</body>
</html>

5

Spustenie aplikácie – pomocou príkazu script/server v príkazovom riadku spustíme aplikačný server WEBrick:

test> ruby script/server
=> Booting WEBrick...
...

Aplikáciu spustíme v akomkoľvek prehliadači zadaním url

http://localhost:3000/say/hello

.

V aplikácii sme vytvorili kontrolér, ktorému sme priradili metódu a pohľad. V tomto prípade sme výnimočne nevytvárali žiadny model, pretože aplikácia nevyužíva prepojenie s databázou. V bežných aplikáciách je model z hľadiska práce s dátami nevyhnutný.

Asociácie

Väčšina novodobých aplikácií obsahuje veľké množstvo tabuliek, medzi ktorými je potrebné vytvoriť čo najefektívnejšie prepojenia. K tomuto účelu slúžia bežné rozšírenia modelov, asociácie. Asociácie sú odvodené od prirodzených vzťahov medzi objektami v reálnom živote: užívateľ píše viacero článkov, články majú viacero komentárov od viacerých užívateľov a pod. V relačných databázových systémoch, ako MySQL, sú tabuľky prepojené odvolaním sa na cudzí kľúč v jednej tabuľke a primárnym kľúčom v druhej. Príkladom je prepojenie tabuliek rozvrhu - predmetov (subjects) a študijných kombinácií (study_combinations), obrázok 4.3.:

Obrázok 4.3.: Vzťah medzi tabuľkami subjects a study combinations

V tomto prípade je stĺpec pomenovaný study_combination_id v tabuľke subjects použitý na identifikáciu priradenej študijnej kombinácie. V konvenciách Rails je cudzí kľúč uvedený v singulárnej forme, malými písmenami a pomenovaný po danej tabuľke s príponou _id na konci.

Pozn.: Pri konvenciách pomenovávania treba brať do úvahy, že Rails pracuje so slovníkom anglického jazyka, vrátane skloňovania podstatných mien. Pre slovenského programátora je preto z hľadiska efektivity vhodné riadiť sa týmito konvenciami a používať pri pomenovávaní tabuliek, modelov, kontrolérov a pohľadov anglické výrazy. Konfigurácia vlastných názvov v slovenčine je možná a pomerne jednoduchá, napriek tomu je pri takomto postupe zvýšené riziko výskytu chýb v kóde a značne sa tým predlžuje čas programovania a ladenia.

Deklarácia asociácií

Správu asociácií má v Rails na starosti Active Record. Použiť je možné 4 rôzne typy asociácií:

  • has_one
  • has_many
  • belongs_to
  • has_and_belongs_to_many

Názvy inštrukcií sú volené tak, aby bolo intuitívne pochopiteľné ich využitie. Teda je prirodzené vysloviť tvrdenie, že jedna študijná kombinácia má viacero predmetov (has_many) a jeden predmet patrí do určitej študijnej kombinácie (belongs_to).

Asociácie one-to-one = has_one + belongs_to

Tento typ asociácie sa používa v prípade, keď riadok v jednej tabuľke je prepojený presne s jedným riadkom inej. Príkladom je prepojenie tabuliek zamestnancov (emloyees) a adries (adresses). Každý zamestnanec má jednu konkrétnu adresu a každá adresa patrí niektorému zo zamestnancov (pozri Obrázok 4.4.). V tomto prípade je potrebné v tabuľke adries vytvoriť atribút employee_id a modely doplniť o príslušné asociácie:

class Emloyee < ActiveRecord::Base
	has_one :address
end

class Adress < ActiveRecord::Base
	belongs_to :employee
end
Obrázok 4.4.: Vzťah has_one - belongs_to

Základné metódy, ktoré sa najčastejšie používajú v súvislosti s has_one asociáciou sú zobrazené v tabuľke 4.3.:

Tabuľka 4.3.: Metódy asociácie has_one v príklade Employee/Adress
Metóda Popis
@employee.adress

@employee.address=(address)

@employee.address.nil?

@employee.build_adress(attributes={})


@employee.create_address(attributes={})
vracia priradený objekt tabuľky adresses: vracia nil pokiaľ objekt neexistuje
priradí asociovaný (Adress) objekt, jeho primárny kľúč definuje ako cudzí kľúč (bez uloženia do tabuľky)
vracia hodnotu true pokiaľ neexistuje asociovaný Address objekt
vracia nový Adress objekt inicializovaný aj s atribútmi, prepojený s @employee pomocou cudzieho kľúča (bez uloženia do tabuľky)
vraca nový Adress objekt inicializovaný aj s atribútmi, prepojený s @employee pomocou cudzieho kľúča a ukladá záznam do tabuľky

Asociácie one-to-many = has_many + belongs_to

Asociácia one-to-many definuje situáciu keď riadok v jednej tabuľke je vzťahovo prepojený s jendným alebo viacerými riadkami v inej tabuľke. Autor môže napísať viacero článkov a každý článok patrí určitému autorovi. V tabuľke článkov (articles) je potrebný atribút definujúci autora author_id (obrázok 4.5.). Modely sú doplnené o asociácie:

class Author < ActiveRecord::Base
   has_many :articles
end

class Article < ActiveRecord::Base
   belongs_to :author
end
Obrázok 4.5.: Vzťah has_many - belongs_to

Najčastejšie využívané metódy sú v tabuľke 4.4:

Tabuľka 4.4: Metódy asociácie has_many v použití modelov Author a Article
Metóda Popis
@author.articles

@author.articles=(articles)
@author.articles << article

@author.articles.delete(articles)

@author.articles.clear

@author.articles.size

@author.articles.find
vracia pole priradených článkov; prázdne pole vracia v prípade, že sa nenašiel žiadny záznam
zamení pôvodnú kolekciu článkov za zvolenú
pridáva jeden alebo viac záznamov do kolekcie a ukladá ich cudzie kľúče
odstráni požadované množstvo článkov z kolekcie nastavením ich cudzích kľúčov na hodnotu NULL
odstráni všetky Article objekty z kolekcie bez toho, aby ich odstránil z databázy
vraca počet objektov triedy Article asociovaných s premennou @author
vyhľadá všetky Article objekty priradené premennej @author podľa zvolených atribútov

Asociácie many-to-many = has_and_belongs_to_many (habtm)

Vzťah many-to-many sa vyskytuje v prípade keď sú dve tabuľky prepojené viacerými záznamami na obidvoch stranách. Pri tomto type prepojenia je potrebná tzv. prepojivacia tabuľka – join table, ktorá sa nachádza medzi tabuľkami a prepája ich pomocou cudzích kľúčov. Názov prepojovacej tabuľky je vytvorený z názvov oboch tabuliek – v prípade tabuliek teacher - subject (učitelia a predmety) je názov subjects_teachers. V tomto prípade je potrebné uplatniť konvenciu, že prvá sa uvádza tá tabuľka, ktorej začiatočné písmeno sa nachádza skôr v abecede. Názvy sú oddelené podčiarkovníkom. Prepojovacia tabuľka je okrem toho výminočná tým, že neobsahuje primárny kľúč id, ktorý je v tomto prípade nepotrebný. Vzťah prepojovacej tabuľky ilustruje obrázok 4.6.:

Obrázok 4.6.: Vzťah has_and_belongs_to_many s použitím prepojovacej tabuľky

Modely doplníme o asociácie:

class Teacher < ActiveRecord::Base
	has_and_belongs_to_many :subjects
end

class Subject < ActiveRecord::Base
	has_and_belongs_to_many :events
end

Pri asociácií typu habtm používame rovnaké metódy, ako v prípade prepojenia has_many, tentokrát v prípade obidvoch tabuliek. Na vytvorenie asociácie sa opäť používa operátor <<:

subject = Subject.find(1,2)	# do premennej uloží predmety s id 1,2
teacher.subjects << subject	# záznamy v premennej priradí do kolekcie

Asociácia many-to-many = has_many :trough

Použitie asociácie habtm je mnohokrát užitočné, súčasne ale aj veľmi obmedzujúce, pretože prepojovacia tabuľka nemôže uchovávať žiadne ďalšie údaje, a preto sa stáva nedostačujúcou pri práci s rozsiahlymi databázami. Robustnejšou alternatívou je vytvorenie asociácie has_many :trough. V tomto prípade sa z tabuľky, ktorá slúži ako prepojovacia, stáva plnohodnotný model, ktorý obsahuje aj ďalšie atribúty. Do týchto je možné ukladať ostatné potrebné dáta. V prípade prepojenia tabuliek dní (days) a mesiacov (months) môžeme vytvoriť prepojovaciu tabuľku dátumov (dates), pričom ku každému dňu v kalendári môžeme uložiť dolnkové dáta, ako napríklad meno, ktoré sa v danom dni nachádzav kalendári:

Obrázok 4.7.: Asociácia many-to-many medzi days a months, cez tabuľku dates

Vloženie asociácií do modelov je pri tejto rozšírenej tabuľke o niečo zložitejšie:

class Date < ActiveRecord::Base
	belongs_to :day
	belongs_to :month
end

class Day < ActiveRecord::Base
	has_many :dates
	has_many :positions, through => :dates, source => :month
end

class Month < AcitveRecord::Base
	has_many :dates
	has_many :parts, through => :dates, source => :day
end

Z príkladu vidíme, že je zmené pomenovanie asociácií, čo vyplýva z filozofie Rails, aby boli vzťahy pomenované čo naprirodzenejšie – deň má viacero pozícií v rôznych mesiacoch určených tabuľkou dátumov, pričom zdrojovou tabuľkou je tabuľka mesiacov. Rovnako každý mesiac sa skladá z mnohýh častí – dní, ktoré sú definované v tabuľke dátumov. Počet dní v decembri môžeme zistiť nasledovne:

Month.find(12).parts.size		# => 31

V jednom riadku môže byť zapísaných viacero metód oddelených bodkou, tak ako v príklade. Najprv metóda find vyhľadá príslušný mesiac podľa primárneho kľúča, následne sa vymedzí pole častí parts tohto mesiaca, ktorého prvky sčíta a výslednú hodnotu navráti metóda size.

Migrácie

V predošlej časti venovanej asociám sme pracovali s tabuľkami a tvorili sme vzťahy medzi nimi. Predpokladom bolo, že tabuľky sú už vytvorené a obsahujú údaje, ktoré sme používali v príkladoch. Rails obsahuje viacero užitočných funkcií nielen pre správu tabuliek, ale aj pre ich tvorbu a úpravu. Tieto sa nazývajú migrácie a patria medzi charakteristické funkcie Rails. Ich využitie je natoľko rôznorodé, že presahuje možnosti tejto práce, a preto spomenieme aspoň najpodstatnejšie rysy migrácií. Migrácie sú súbory popisujúce zmenu v databázovom systéme (vrátane vytvorenia novej tabuľky). Z technického hľadiska sú migrácie triedy nachádzajúce sa v adresári db/migrate aplikácie Rails, Všetky migrácie sú potomkami triedy ActiveRecord::Migration, ktorej metódy používajú. Každá migrácia musí obsahovať metódy tredy up a down. Metóda up sa volá v prípade migrácie z nižšej verzie (popr. žiadnej) na vyššiu. Metóda down sa používa pri návrate k predošlej (staršej) verzii. Migrácie sa obvykle spúšťajú pomocou príkazu rake db:migrate. Trieda zabezpečujúca migrácie funguje tak, že porovná verziu databázy uloženú v tabuľke schema_info a číslo poslednej migrácie v adresári db/migrate a pokiaľ nájde migrácie s číslom väčším ako je číslo databázy, tak tieto migrácie postupne spúšťa. Príkladom môžu byť migrácie z praktickej úlohy, ktorú budeme riešiť v nasledujúcej kapitole – pozri obrázok:

Obrázok 4.8.: Zobrazenie migrácií projektu rozvrh v prostredí NetBeans

Pre správnu funkčnosť migrácií je potrebné splniť dve podmienky:

  • v databázi musí existovať tabuľka schema_info s jedným int stĺpcom version
  • triedy migrácií musia byť v súboroch pomenovaných xxx_nazov_migracie.rb, kde xxx je číslo migrácie

Všetky tieto úkony nemusíme mať na pamäti, pretože Rails obsahuje k tomuto účelu vytvorené generátory a rake tasky, ktoré všetky tieto konvencie vytvoria za nás. V praxi sa migrácie používajú obvykle na vytvorenie novej tabuľky a následne na všetky jej úpravy. Novú migráciu môžeme vygenerovať viacerými spôsobmi, najčastejšie je to pri vytváraní nového modelu, alebo scaffoldu. Model vytvoríme pomocou generátoru skriptom:

script/generate model NazovModelu

Tento príkaz automaticky vygeneruje triedu modelu, unit test a migráciu s už uvedeným konvenčným názvom xxx_nazov_migracie.rb

Scaffold (doslovne lešenie) je akási základná konštrukcia modelu, kontroléru a pohľadov na správu tabuľky (ktorej migrácia sa vytvorí tiež). Scaffold tvoríme podobne príkazom:
script/generate scaffold NazovModelu atr1:typ1 ... atrx:typx 

Ako vidno, v príkaze zadávame iba názov modelu a atribúty tabuľky s definovaním ich typu. Rails generátor priradí meno kontroléru, pohľadom a migrácii automaticky podľa predošlých konvencií. Vytvorenie tabuľky z migrácie docielime jednoduchým príkazom:

rake db:migate

Týmto je automaticky vytvorená nová tabuľka v databázi. Pokiaľ sme ju tvorili spoločne s konštrukciou scaffold, máme vytvorené už aj pohľady a akcie na pridávanie záznamov do tabuľky, editáciu, odstránenie a výpis záznamov tabuľky. Migrácie sú veľmi užitočné aj pri vývoji aplikácií, kedy je každá zmena v tabuľkách uložená v migráciách a pomocou nich reverzibilná do ktoréhokoľvek bodu vývoja.