background image

Wydawnictwo Helion
ul. Koœciuszki 1c
44-100 Gliwice
tel. 032 230 98 63

e-mail: helion@helion.pl

Ajax on Rails

Autor: Scott Raymond
T³umaczenie: Adrian Elczewski
ISBN: 978-83-246-1048-8
Tytu³ orygina³u: 

Ajax on Rails

Format: B5, stron: 336

Zobacz, jak wykorzystaæ potencja³ technologii Ajax i Rails 

w tworzeniu zaawansowanych aplikacji internetowych! 

• 

Jak u¿ywaæ platformy Rails do budowy dynamicznych aplikacji internetowych? 

• 

Jak szybko tworzyæ witryny ajaksowe, wykorzystuj¹c wydajne biblioteki? 

• 

Jak zwiêkszyæ komfort pracy u¿ytkowników Twoich aplikacji internetowych? 

Ajax to olbrzymie mo¿liwoœci w zakresie tworzenia dynamicznych i interaktywnych 
aplikacji internetowych, dzia³aj¹cych niemal tak szybko, jak tradycyjne programy. 
Jednak lepsza jakoœæ witryn wymaga zwykle pisania bardziej skomplikowanego kodu 
i, co za tym idzie, wiêkszych nak³adów pracy i czasu. Tak te¿ by³o do niedawna 
w przypadku Ajaksa, ale obecnie, gdy wzros³a popularnoœæ tej technologii, a ona sama 
dojrza³a, programiœci mog¹ korzystaæ z wielu bibliotek i platform, dziêki którym 
tworzenie efektownych aplikacji internetowych sta³o siê niezwykle proste. 

Ajax on Rails

 to podrêcznik dla programistów, którzy chc¹ szybko i ³atwo budowaæ 

wydajne aplikacje internetowe na bazie dwóch popularnych mechanizmów – technologii 
Ajax oraz platformy Rails. Czytaj¹c go, dowiesz siê, w jaki sposób Ajax umo¿liwia 
kreowanie funkcjonalnych i wygodnych w obs³udze witryn, a tak¿e nauczysz siê 
b³yskawicznie stosowaæ tê technologiê w oparciu o biblioteki Prototype i scipt.aculo.us 
oraz kompletn¹ platformê do tworzenia aplikacji internetowych, czyli Rails. Poznasz te¿ 
sposoby sprawnego diagnozowania aplikacji ajaksowych oraz zapewnisz im 
bezpieczeñstwo i wydajnoœæ, aby udostêpniaæ swym klientom produkty najwy¿szej klasy. 

• 

Przegl¹d mechanizmów technologii Ajax 

• 

Dzia³anie platformy Rails 

• 

Ajaksowe przesy³anie danych za pomoc¹ biblioteki Prototype 

• 

Dodawanie efektów do witryn przy u¿yciu biblioteki scipt.aculo.us 

• 

Generowanie kodu JavaScript za pomoc¹ szablonów RJS 

• 

Zwiêkszanie u¿ytecznoœci aplikacji 

• 

Diagnozowanie aplikacji na platformie Rails 

• 

Zapewnianie bezpieczeñstwa programu 

• 

Zwiêkszanie wydajnoœci aplikacji 

background image

  

  

  

  

  

3

Spis tre

ļci

Przedmowa  .....................................................................................................................7

   1.   Wprowadzenie  ..............................................................................................................11

Dla kogo jest ta ksiñĔka  

11

Czym jest Ajax?  

12

Czym jest Rails  

18

„Twój Ajax w moim Rails”  

21

Nabieranie prödkoĈci  

21

Podsumowanie  

27

   2.   Pierwsze kroki   ..............................................................................................................29

Staromodny sposób  

29

Prototype oraz inne biblioteki JavaScript  

33

Rails pojawia siö na horyzoncie  

35

Podsumowanie 

40

  3.  Wprowadzenie do Prototype ....................................................................................... 41

Ustawianie sceny 

41

ãñcza w Ajaksie 

44

Formularze 

48

Formularze w Ajaksie 

51

Przyciski 

52

Obserwatory formularza 

54

Podsumowanie 

55

  4.  Wprowadzenie do script.aculo.us  ...............................................................................57

Efekty wizualne 

57

Przeciñgnij i upuĈè 

62

Podsumowanie 

70

background image

4  

_   Spis treļci

  5.  RJS .................................................................................................................................. 71

Instrukcje zamiast danych 

71

Umieszczenie R w skrócie RJS 

72

Przykäady z Ĕycia wziöte 

85

Podsumowanie 

87

  6.  U

Ŝytecznoļë Ajaksa  ......................................................................................................89

Zasady uĔytecznoĈci 

90

Kontekst Internetu 

94

UĔytecznoĈè w Internecie 

97

Programowanie uwzglödniajñce róĔne przeglñdarki 

103

Podsumowanie 

107

  7.  Testowanie i usuwanie b

ĥýdów .................................................................................109

Usuwanie bäödów 

110

Testowanie 

122

Podsumowanie 

134

  8.  Bezpiecze

ħstwo .......................................................................................................... 135

Zdrowy sceptycyzm: nie ufaè danym wejĈciowym uĔytkownika 

135

Hashowanie haseä 

144

Uciszanie logów 

145

Polityka tej samej domeny 

146

UĔywanie i naduĔywanie metod HTTP 

148

Szyfrowanie i certyfikaty bezpieczeþstwa 

151

Lista mailingowa o bezpieczeþstwie w Rails 

152

Podsumowanie 

152

  9.  Wydajno

ļë  ................................................................................................................... 153

ćrodowiska projektowe i produkcyjne 

153

Przechowywanie sesji 

154

Buforowanie wyjĈcia 

155

Pakowanie zasobów 

160

Postöpowanie z däugo dziaäajñcymi zadaniami 

162

Podsumowanie 

164

  10.  Informator o Prototype  .............................................................................................. 165

Wsparcie Ajaksa 

166

Manipulacja DOM 

172

Wbudowane rozszerzenia 

185

background image

  

  

  

Spis tre

ļci   _  

5

  11.  Informator o script.aculo.us  ....................................................................................... 199

Efekty wizualne 

199

Przeciñgnij i upuĈè 

209

Kontrolki 

218

Rozszerzenia klasy element 

226

Konstruktor DOM 

228

Testowanie jednostkowe JavaScript 

229

Metody narzödziowe 

232

 

  Przyk

ĥad A Quiz ...........................................................................................................233

 

  Przyk

ĥad B Galeria zdjýë  ............................................................................................ 249

 

  Przyk

ĥad C Aplikacja wspóĥpracy w grupie  ...............................................................267

 

  Skorowidz  ................................................................................................................... 315

background image

29

ROZDZIA

Ĥ 2.

Pierwsze kroki

O, Ajaksie! ZnowuĔ Ciö przyzywam.

— 

Sofokles

W tym rozdziale gäównym zamysäem jest zrobienie rundki, maäymi kroczkami, po naprawdö
prostych przykäadach wykorzystania technologii Ajax. Rails dostarcza wiele moĔliwoĈci two-
rzenia zäoĔonych interakcji w technologii Ajax z uĔyciem bardzo maäej iloĈci kodu. Ale Ĕeby
zrozumieè,  co  siö  dzieje  „pod  maskñ”,  kaĔdy  powinien  byè  obeznany  z  najniĔszym  pozio-
mem  dziaäania  technologii  Ajax  (np.  obiektem 

XMLHttpRequest

).  Po  przyswojeniu  treĈci  tej

ksiñĔki tworzenie obiektu 

XMLHttpRequest

 za pomocñ biblioteki Prototype lub bez jej uĔycia

nie bödzie stanowiäo problemu. Czytelnik bödzie potrafiä z pomocñ Rails utworzyè proste inte-
rakcje w technologii Ajax bez pisania jakiegokolwiek kodu w JavaScripcie. Z tym zaäoĔeniem
zdobödziemy wiedzö na temat dziaäania pomocników Rails oraz dowiemy siö, jak wielu käo-
potów one oszczödzajñ.

Dla czytelników, którzy mieli okazjö zapoznaè siö z Rails i znajñ podstawy Ajaksa, ten roz-
dziaä bödzie okazjñ do odĈwieĔenia wiedzy, warto przynajmniej przyjrzeè siö przykäadom.

Staromodny sposób

ēeby rozpoczñè, wykonajmy najprostszñ rzecz do zrobienia z uĔyciem technologii Ajax: klik-
nijmy äñcze i zaprezentujmy odpowiedĒ z serwera — uĔywajñc bezpoĈrednio 

XMLHttpRequest

,

bez pomocy Prototype czy pomocników Rails dla JavaScript.

UĔywanie 

XMLHttpRequest

 jest czösto opisywane jako coĈ wyjñtkowo trudnego. ãatwo zauwa-

Ĕyè, Ĕe po zdobyciu odrobiny doĈwiadczenia i poznaniu kilku nowych koncepcji nie jest to aĔ
tak zawiäe, jak moĔna by byäo siö spodziewaè na podstawie powszechnej opinii.

Rozpoczynanie projektu

Osoby, które nie stworzyäy przykäadu szkieletu Rails w poprzednim rozdziale, powinny zrobiè
to teraz, wpisujñc w wierszu poleceþ systemowych:

rails ajaxonrails
cd ajaxonrails
script/server

background image

30

_

Rozdzia

ĥ 2. Pierwsze kroki

Za pomocñ przeglñdarki naleĔy otworzyè stronö http://localhost:3000/ — powinien siö pojawiè ekran
powitalny Rails (dla celów przyszäego projektowania warto pamiötaè, Ĕe 

script/server

uruchamia na porcie 3000 serwer HTTP). Teraz utwórzmy nowy kontroler, który nazwiemy

Chapter2Controller

,  z  akcjñ 

myaction

.  (Po  uruchomieniu  serwera  w  jednym  terminalu

warto otworzyè inny).

script/generate controller chapter2 myaction

Generator Rails jest uĔywany do uzupeäniania szkieletu — przewaĔnie przez tworzenie
nowych  kontrolerów  i  modeli.  OczywiĈcie  moĔna  by  w  prosty  sposób  utworzyè
kontroler plików röcznie, ale uĔywanie generatora jest oszczödnoĈciñ pisania — co
zapobiega robieniu bäödów.

Generator ma takĔe inny skutek: za kaĔdym razem, gdy generuje siö kontroler, two-
rzony jest równieĔ wspóäpracujñcy z nim plik testów funkcjonalnych. To sposób Rails
na  przypominanie,  Ĕe  testowanie  jest  waĔnñ  czöĈciñ  tworzenia  aplikacji.  Aby  do-
wiedzieè  siö  wiöcej  o  dostöpnych  generatorach  i  ich  opcjach,  naleĔy  uruchomiè
script/generate bez Ĕadnych argumentów.

Teraz trzeba przejĈè do http://localhost:3000/chapter2/myaction. NaleĔy siö spodziewaè nowo utwo-
rzonego widoku jak na rysunku 2.1.

Rysunek 2.1. Nowo utworzony kontroler Rails i jego widok

Proszö zauwaĔyè, Ĕe domyĈlnie pierwsza czöĈè adresu URL determinuje kontroler, a druga akcjö
— metodö w ramach kontrolera. Teraz bödziemy edytowaè szablon dla tej akcji, do którego pro-
wadzi ĈcieĔka app/views/chapter2/myaction.rhtml. Dodajemy ten fragment HTML na dole pliku.

<p><a href="#" onclick="alert('Cze

Łð !');">Inline alert( )</a></p>

Jak moĔna zauwaĔyè, tworzymy akapit z prostym äñczem — ale zamiast standardowego atrybutu

href

  uĔywamy 

onclick

,  do  którego  dostarczamy  fragment  kodu  JavaScript  do  uruchomie-

nia. Po odĈwieĔeniu przeglñdarki i klikniöciu äñcza pojawi siö to, co przedstawia rysunek 2.2.

Wiöcej niĔ jedna czy dwie instrukcje wstawione do atrybutu 

onclick

 mogäyby szybko staè siö

niewygodne.  PrzenieĈmy  kod  do  osobnej  funkcji  JavaScript  poprzez  dodanie  tego,  co  znaj-
duje siö poniĔej:

<p><a href="#" onclick="customAlert( ); ">Wywo

Īanie wĪasnej funkcji</a></p>

<script type="text/javascript">
  function customAlert( ) {
    alert('Powitanie z w

Ĩasnej funkcji.');

  }
</script>

background image

Staromodny sposób

_

31

Rysunek 2.2. Prosta ramka ostrzegawcza

Proszö  spróbowaè  ponownie  odĈwieĔyè  stronö  i  zobaczyè,  co  siö  stanie.  Rezultat  powinien
byè w zasadzie taki sam jak poprzednio.

Koniec rozgrzewki, teraz zajmiemy siö Ajaksem. (Ale proszö pamiötaè, Ĕe wciñĔ zaglñdamy
„pod maskö” — pod koniec tego rozdziaäu  sporo  zäoĔonoĈci  Rails  znacznie  siö  uproĈci).  Po
pierwsze, musimy zdefiniowaè nowñ akcjö w kontrolerze, app/controllers/chapter2_controller.rb.
Teraz znajduje siö tam akcja 

myaction

, wiöc nastöpnñ nazwijmy 

myresponse

. Aby to zrobiè,

naleĔy  utworzyè  nowy  plik,  myresponse.rhtml  w  katalogu  app/views/chapter2.  Do  zawartoĈci
pliku wprowadĒmy:

Powitanie z serwera.

ēeby  mieè  pewnoĈè,  Ĕe  wszystko  dziaäa,  proszö  odwiedziè  tö  akcjö  w  swojej  przeglñdarce
pod  adresem  http://localhost:3000/chapter2/myresponse  —  bödzie  widoczne  to,  co  przedstawia
rysunek 2.3.

Rysunek 2.3. Wynik akcji myresponse

Teraz wróèmy do myaction.rhtml i dodajmy kolejny fragment kodu HTML i JavaScript.

<p><a href="#" onclick="serverSideAlert( );">Wywo

Īanie funkcji po stronie serwera

</a></p>
<script type="text/javascript">
  function serverSideAlert( ) {
    var request = new XMLHttpRequest( );
    request.open('get', '/chapter2/myresponse', false);
    request.send(null);
    alert(request.responseText);
  }
</script>

background image

32

_

Rozdzia

ĥ 2. Pierwsze kroki

Za pomocñ przeglñdarki przejdĒmy z powrotem do http://localhost:3000/chapter2/myaction i klik-
nijmy nowe äñcze. JeĈli wszystko poszäo dobrze, powinna siö pojawiè wiadomoĈè z serwera,
taka jak na rysunku 2.4. Ostrzegamy, Ĕe ten przykäad nie bödzie dziaäaä we wczeĈniejszych niĔ
siódma wersjach Internet Explorera (ten problem podejmiemy póĒniej).

Rysunek 2.4. Rezultat pierwszego wywoäania w Ajaksie

Teraz do czegoĈ doszliĈmy! ēeby siö przekonaè, warto zerknñè na terminal, gdzie uruchomiony
jest 

script/server

. Za kaĔdym razem, gdy klika siö „zajaksowane” äñcze, rejestrowane bö-

dzie nowe klikniöcie:

Processing Chapter2Controller#myresponse [GET]
  Parameters: {"action"=>"myresponse", "controller"=>"chapter2"}
Completed in 0.00360 (278 reqs/sec) | Rendering: 0.00027 (7%) |
  200 OK [http://localhost/chapter2/myresponse]

DuĔym  problemem  omawianego  przykäadu  jest  to,  Ĕe  nie  dziaäa  on  w  jednej  z  najbardziej
rozpowszechnionych przeglñdarek, Internet Explorer 6. Przyczynñ jest obiekt ActiveX w im-
plementacji 

XMLHttpRequest

 Microsoftu (a wäaĈciwie dwa takie obiekty, co zaleĔy od wersji IE),

który musi byè tworzony w inny sposób. ēeby zlikwidowaè ten problem i sprawiè, aby nasz
przykäad dziaäaä poprawnie we wszystkich przeglñdarkach, tworzymy maäñ funkcjö. Oto wersja
przyjazna dla IE:

<p><a href="#" onclick="IEAlert( );">Wywo

Īanie serwera (dziaĪajîce pod IE)</a></p>

<script type="text/javascript">
  function IEAlert( ) {
    function getRequestObject( ) {
      try { return new XMLHttpRequest( ) } catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
      return false
    }
    var request = getRequestObject( );
    request.open('get', '/chapter2/myresponse', false);
    request.send(null);
    alert(request.responseText);
  }
</script>

Ta wersja jest taka sama jak wczeĈniejsza, z wyjñtkiem tego Ĕe zamiast tworzyè bezpoĈrednio
obiekt 

XMLHttpRequest

, wywoäywana jest funkcja 

getRequestObject()

, która wybiera moĔ-

liwñ opcjö. Ta funkcja robi uĔytek z deklaracji 

try

 w JavaScripcie, która jest wykorzystywana

background image

Prototype oraz inne biblioteki JavaScript

_

33

do wyäapywania wyjñtków i täumienia ich. (Ten przykäad wprowadza takĔe ideö deklarowa-
nia funkcji w funkcji, która moĔe byè nowoĈciñ dla niektórych programistów).

Dotychczas  odrobinö  oszukiwaliĈmy,  poniewaĔ  wywoäanie  Ajaksa  nie  jest  asynchroniczne.
Decyduje  o  tym  trzeci parametr  w  metodzie 

request.open()

.  Do  tej  pory  zakäadaliĈmy,  Ĕe

wywoäanie  nie  byäo  synchroniczne.  W  zwiñzku  z  tym 

request.send()

  byäo  blokujñce  —  in-

terpreter JavaScript zatrzymywaä wykonywanie w tym wierszu i nie przechodziä do nastöpnego,
dopóki nie nadeszäa odpowiedĒ z serwera. ēeby sprawiè, aby wywoäanie byäo asynchroniczne,
musimy trochö zmieniè kod. Proszö dodaè ten fragment kodu do myaction.rhtml:

<p><a href="#" onclick="asyncAlert( )">Asynchroniczne wywo

Īanie serwera</a></p>

<script type="text/javascript">
  function asyncAlert( ) {
    function getRequestObject( ) {
      try { return new XMLHttpRequest( ) } catch (e) {}
      try { return new ActiveXObject("Msxml2.XMLHTTP") } catch (e) {}
      try { return new ActiveXObject("Microsoft.XMLHTTP") } catch (e) {}
      return false
    }
    var request = getRequestObject( );
    request.open('get', '/chapter2/myresponse');
    request.onreadystatechange = function( ) {
      if(request.readyState == 4) alert(request.responseText);
    }
    request.send(null);
  }
</script>

We  wszystkich  poprzednich  przykäadach  wywoäywaliĈmy 

request.send()

  i  natychmiast  po-

tem odwoäywaliĈmy siö do 

request.responseText()

. Teraz, gdy wysyäamy asynchroniczne

Ĕñdanie, odpowiedĒ niekoniecznie wraca po zakoþczeniu wywoäania. Aby rozwiñzaè ten pro-
blem, obiekt 

XMLHttpRequest

 ma atrybut 

readyState

, który zmienia siö w czasie cyklu Ĕycia

Ĕñdania. Ma takĔe atrybut 

onreadystatechange

, gdzie moĔna zdefiniowaè funkcjö, która bö-

dzie wywoäywana za kaĔdym razem, gdy status 

readyState

 bödzie siö zmieniaä. W tym przy-

käadzie  definiujemy  funkcjö,  która  sprawdza,  czy 

readyState

  jest  równy 

4

  (co  oznacza,  Ĕe

Ĕñdanie siö zakoþczyäo; kody 

readyState

 opisane sñ w peäni w rozdziale 3.), a jeĈli tak, wy-

Ĉwietla okienko z komunikatem. Opanowanie asynchronicznych zdarzeþ moĔe wymagaè trochö
czasu, ale jest zasadniczñ czöĈciñ röcznego programowania w Ajaksie.

Prototype oraz inne biblioteki JavaScript

Osoby, które dopiero zaczynajñ swojñ przygodö z Ajaksem, prawdopodobnie zaczöäy zauwaĔaè,

Ĕe  pisanie  w  czystym  Ajaksie,  pozbawionym  wsparcia  dodatkowych  bibliotek  albo  metod
pomocniczych, nie jest powszechne. W ogóle pomysä pisania wiöcej niĔ tuzina wierszy kodu
w celu stworzenia najprostszego moĔliwego zadania jest odpychajñcy.

Dziesiñtki bibliotek JavaScript wychodzñ z siebie, Ĕeby sprawiè, by Ajax byä äatwiejszy w obsäu-
dze. Jednñ z najbardziej popularnych jest Prototype, która stanowi czöĈè Rails. Bödziemy oma-
wiaè Prototype gruntownie w rozdziale 10., ale teraz przyjrzyjmy siö pewnym przykäadom.
Zanim  zaczniemy  coĈ  innego,  przeróbmy  ponownie  ostatni  przykäad,  tym  razem  uĔywajñc
Prototype. Oto nowy fragment do dodania:

<script src="/javascripts/prototype.js" type="text/javascript">
</script>
<p><a href="#" onclick="prototypeAlert( );">Wywo

Īanie funkcji z Prototype</a></p>

background image

34

_

Rozdzia

ĥ 2. Pierwsze kroki

<script type="text/javascript">
 function prototypeAlert( ) {
  new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
   alert(request.responseText);
  }})
 }
</script>

Proszö zwróciè uwagö na pierwszy wiersz, gdzie wäñczamy äadowanie Ēródäa pliku prototype.js,
by móc z niego korzystaè na naszej stronie. Przy pierwszym tworzeniu szkieletu aplikacji Rails
kopia Prototype byäa umieszczona w katalogu public/javascripts. Wewnñtrz funkcji 

prototype-

Alert()

 pierwszy wiersz tworzy nowñ instancjö 

Ajax.Request

, jednej z klas Prototype. Pierwszy

wywoäywany argument jest adresem URL, drugi — jest obiektem JavaScript — kolekcjñ par
kluczy – wartoĈci, które zachowujñ siö podobnie do map albo tablic asocjacyjnych w innych
jözykach  programowania.  W  tym  przypadku  jedynñ  wartoĈciñ  jest 

onSuccess

  okreĈlajñca

funkcjö wywoäywanñ jako funkcja zwrotna.

Proszö zwróciè uwagö, iĔ w tym przykäadzie nie ma Ĕadnego kodu specyficznego dla obsäugi
wersji 

XMLHttpRequest

  dla  przeglñdarki  IE  i  Ĕadnej  obsäugi  kodów 

readyState

.  Prototype

obsäuguje te szczegóäy, udostöpniajñc programiĈcie duĔo czystsze API.

Dotychczas wszystkie nasze przykäady tworzyäy okno komunikatu 

alert()

 — które, w rze-

czywistych aplikacjach, prawdopodobnie nie jest najczöĈciej uĔywane. Znacznie czöĈciej do-
dawana jest nowa zawartoĈè strony albo modyfikowana dotychczasowa. Oto nowy fragment
do dodania:

<p><a href="#" onclick="updateElement( )">Uaktualnij element </a></p>
<p id="response"></p>
<script type="text/javascript">
  function updateElement( ) {
    new Ajax.Request('/chapter2/myresponse', { onSuccess: function(request) {
      $('response').update(request.responseText);
    }})
  }
</script>

Proszö zauwaĔyè róĔnice miödzy powyĔszym a wczeĈniejszym przykäadem: dodany zostaä nowy
pusty element akapitu z atrybutem 

id="response"

, który bödzie przechowywaä odpowiedĒ

otrzymanñ z serwera. Funkcja 

onSuccess

 zostaäa zmieniona, zamiast wywoäania 

alert()

 funkcja

ta umieszcza tekst odpowiedzi w elemencie 

response

 (uĔywajñc metody 

update()

 z biblio-

teki Prototype, która ustawia wäaĈciwoĈè elementu 

innerHTML

). Symbol dolara jest faktycznie

nazwñ  funkcji  definiowanej  przez  Prototype,  która  pobiera  ciñg  znaków  i  zwraca  element
HTML na podstawie tego ID. PoniewaĔ aktualizacja elementów HTML bödzie bardzo czösto
wykonywanym zadaniem, Prototype uäatwia to poprzez 

Ajax.Updater.

 Proszö to sprawdziè:

<p><a href="#" onclick="updater( )">Modernizuj za pomoc

î Ajax.Updater</a></p>

<p id="response2"></p>
<script type="text/javascript">
  function updater( ) {
    new Ajax.Updater('response2', '/chapter2/myresponse');
  }
</script>

Funkcja $() w Prototype bödzie uĔywana bardzo czösto, z bliska wyglñda niezwy-
kle wartoĈciowo. Na pierwszy rzut oka jest prostym opakowaniem dla standardowej
metody DOM document.getElementById z nazwñ duĔo prostszñ do zapamiöta-
nia i sprawiajñcym wraĔenie skäadni JavaScript. Ale to wiöcej niĔ tylko opakowanie.

background image

Rails pojawia si

ý na horyzoncie

_

35

Przede wszystkim moĔe przyjñè dowolnñ liczbö argumentów, wiöc moĔna otrzymaè
kilka elementów jednoczeĈnie. Ponadto kaĔdy zwracany element jest automatycznie
rozszerzany o potöĔny zestaw metod omówionych w rozdziale 10.

Prawdopodobnie  najbardziej  istotne  jest,  Ĕe  jeĈli  przekaĔe  siö  do  metody  $()  ciñg
znaków, zwróci ona element DOM z tym wäaĈnie ID. Ale jeĈli przekaĔe siö obiekt ja-
kiegokolwiek innego typu — powiedzmy element DOM — w prosty sposób zwróci
ten obiekt bez zmian. Wynikiem jest to, Ĕe moĔna uĔywaè $() z wartoĈciami, nawet
jeĈli nie jest siö pewnym, czy wartoĈci te sñ ciñgiem znaków czy elementem DOM, co
sprawia, Ĕe API JavaScript jest mniej podatne na bäödy.

Proszö  zwróciè  uwagö,  Ĕe  ten  przykäad  nie  ma  w  sobie  funkcji 

onSuccess

,  tutaj 

Ajax.Updater

pobiera tylko dwa argumenty: ID elementu HTML, który ma byè zaktualizowany, i URL Ĕñ-
dania. 

Ajax.Updater

 wywoäuje URL i automatycznie tworzy funkcjö 

onComplete

 säuĔñcñ do

zaktualizowania okreĈlonego elementu DOM za pomocñ wartoĈci 

response.Text

. Tak jak

w przypadku 

Ajax.Request

, ostatni argument jest zestawem opcji. Jedna z nich jest nazwana

insertion

. Pozwala na pójĈcie duĔo dalej niĔ prosta zamiana zawartoĈci elementu, zamiast

tego umoĔliwia wstawienie zawartoĈci w rozmaitych punktach. Istniejñ cztery typy wstawia-
nia: 

Before

Top

Bottom

 oraz 

After

. Na przykäad:

<p><a href="#" onclick="appendToElement( )">Dodaj do elementu</a></p>
<p id="response3"></p>
<script type="text/javascript">
  function appendToElement( ) {
    new Ajax.Updater('response3', '/chapter2/myresponse',
      { insertion:Insertion.Bottom });
  }
</script>

Kiedy kliknie siö äñcze za pierwszym razem, odpowiedĒ z serwera bödzie dodana do tej stro-
ny tak jak poprzednio. Przy póĒniejszych klikniöciach, zamiast zastñpiè wczeĈniejszñ zawar-
toĈè, kolejne odpowiedzi bödñ doäñczane do poprzednich.

Proszö zauwaĔyè, Ĕe zdoäaliĈmy zredukowaè doĈè zäoĔone zachowanie do postaci funkcji z za-
ledwie jednñ instrukcjñ. Aby zatoczyè peäne koäo, moĔemy zredukowaè kod do postaci poje-
dynczego atrybutu 

onclick

:

<p><a href="#" onclick="new Ajax.Updater('response4',
'/chapter2/myresponse', { insertion:Insertion.Bottom });">
Dodaj do elementu</a></p>
<p id="response4"></p>

Jak bödzie moĔna siö wkrótce przekonaè, jest to dokäadnie ten sam kod, który generujñ pomoc-
niki JavaScript w Rails.

Rails pojawia si

ý na horyzoncie

Rails dostarcza dogodnñ integracjö z Prototype w formie metod pomocników, które generujñ
wywoäania funkcji udostöpnianych przez Prototype. Odkryjemy, jak tworzyè Ajaksa bez pi-
sania jakiegokolwiek kodu w JavaScripcie, uĔywajñc metody pomocnika 

link_to_remote()

.

Po pierwsze, musimy cofnñè siö odrobinö i dowiedzieè siö, jak Rails obsäuguje widoki.

background image

36

_

Rozdzia

ĥ 2. Pierwsze kroki

Podstawy ERb

Osoby, które kiedykolwiek korzystaäy z PHP, ColdFusion, ASP, JSP albo czegoĈ podobnego,
uznajñ, Ĕe jest to znajoma koncepcja. Wbudowany Ruby (Erb, ang. Embedded Ruby) pozwala
na  äñczenie  fragmentów  Ruby  z  HTML-em.  ERb  definiuje  zestaw  specjalnych  znaczników,
które sñ interpretowane jako Ruby; wszystko inne jest traktowane jako czysty HTML i zwra-
cane w nienaruszonej postaci. Oto te specjalne znaczniki:

<%= %>

Najcz

ýļciej uŜywany, zawiera wyraŜenie Ruby — którego wynik zwracany jest w miejscu znacznika.

<%= -%>

Dzia

ĥa tak jak powyŜszy, ale usuwa znaki nowego wiersza znajdujéce siý za tym znacznikiem, co pozwala na

czystsze zorganizowanie plików szablonów bez zb

ýdnych pustych miejsc w wynikowych dokumentach HTML.

<% %>

Przechowuje fragment kodu Ruby, ale nie zwraca niczego.

<% -%>

Dzia

ĥa tak jak powyŜszy, ale usuwa znaki nowego wiersza znajdujéce siý za tym znacznikiem.

<%# %>

To jest komentarz Ruby, który jest ignorowany i niczego nie zwraca.

Teraz spójrzmy na przykäad.

Czy  pamiötasz  dyskusjö  o  MVC  z  rozdziaäu  1.?  Tutaj  MVC  zaczyna  odgrywaè  swojñ  rolö.
Zwykle kontroler bödzie otrzymywaè Ĕñdanie wyĈwietlenia strony i przygotowywaè dane po-
trzebne dla widoku. W Rails dane te sñ umieszczane w zmiennych instancji (które sñ rozpoznawane
dziöki brzydkiemu znakowi 

@

, od którego siö zaczynajñ ich nazwy). Proszö sobie zatem wy-

obraziè, Ĕe mamy takñ akcjö kontrolera:

def myaction
  @foo = "Witaj, 

Łwiecie!"

end

Akcja definiuje zmiennñ nazwanñ 

@foo

 i przypisuje jej äaþcuch znaków 

Witaj, 

Łwiecie!

. Nasz

szablon mógäby wiöc zawieraè coĈ takiego:

<%= @foo %>

I, gdy szablon jest wywoäywany, 

<%= @foo %>

 bödzie zastñpione przez 

Witaj, 

Łwiecie!

. Caä-

kiem oczywista sprawa. W praktyce przewaĔnie chce siö wykorzystaè zmiennñ w strukturze
HTML, np.:

<h1><%= @foo %></h1>

PoniewaĔ znacznik 

<% %>

 nie produkuje Ĕadnego wyjĈcia, najczöstsze jego uĔycie zwiñzane jest

ze strukturami kontrolnymi, takimi jak instrukcja 

if

 i iteracje 

each

. W odróĔnieniu od innych

systemów szablonowych nie istnieje skäadnia specyficzna dla ERb dla tych konstrukcji; ERb
uĔywa zwyczajnych wyraĔeþ jözyka Ruby. Kilka przykäadów:

<% if @page_title %><h1><%= @page_title %></h1><% end %>
<% unless @names.empty? %>
  <ul>
    <% @names.each do |name| %><li><%= name %></li><% end %>
  </ul>
<% end %>

Proszö spojrzeè na drugi wiersz. Zaczyna siö od wyraĔenia  warunkowego 

unless

  —  odpo-

wiednika Ruby dla 

if not

. Proszö zwróciè teĔ uwagö na 

@names.empty?

. Wszystkie tablice

Ruby korzystajñ z metody nazwanej 

empty?

 — zazwyczaj nazwy metod Ruby zwracajñcych

prawdö  lub  faäsz  koþczñ  siö  znakiem  zapytania.  Ostatniñ  sprawñ  wartñ  podkreĈlenia  jest
czwarty wiersz. Wywoäanie metody 

each

 dla 

@names

 iteruje przez kaĔdy element tablicy, zatem

kod ten przejdzie caäñ tablicö 

@names

 i zwróci listö elementów w HTML dla kaĔdego imienia.

background image

Rails pojawia si

ý na horyzoncie

_

37

Uk

ĥad graficzny

Ukäad graficzny tworzñ specjalne szablony, które przechowujñ powszechnie uĔywane znacz-
niki dla wielokrotnie wykorzystywanych widoków. W innych systemach szablonowych jest to
czösto osiñgane poprzez tworzenie plików z szablonami nagäówka i stopki, które sñ wäñczane
do szablonu strony. Rails dziaäa odwrotnie — nagäówki i stopki sñ zdefiniowane w jednym
pliku wystroju graficznego, a stamtñd doäñczana jest treĈè strony. Pliki ukäadu graficznego sñ
przechowywane w app/views/layouts i domyĈlnie Rails najpierw poszuka tego, którego nazwa
jest  taka  sama  jak  aktualnego  kontrolera,  np.  chapter2.rhtml.  JeĈli  Rails  takiego  pliku  ukäadu
graficznego nie znajdzie, poszuka pliku nazwanego application.rhtml. ZawartoĈè pliku wystroju
graficznego moĔe wyglñdaè nastöpujñco:

<html>
  <head>
    <title>Moja Aplikacja Rails </title>
    <%= javascript_include_tag "prototype" %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

NajwaĔniejszñ czöĈciñ, o której naleĔy wspomnieè, jest 

<%= yield %>

. Jej zadaniem jest doäñ-

czenie kodu z szablonu widoku. Innymi säowy, spowoduje wstawienie kodu szablonu widoku
do pliku ukäadu graficznego. Proszö nie zapominaè o doäñczeniu tego wywoäania w pliku ukäadu
graficznego, bo w przeciwnym razie strony mogñ siö wydawaè puste.

Cz

ýļci

CzöĈci sñ podszablonami zaprojektowanymi dla fragmentów zäoĔonych ze znaczników, które
wykorzystywane  sñ  ponownie  —  albo  np.  chce  siö  je  trzymaè  w  osobnym  pliku,  Ĕeby  pliki
szablonów pozostaäy przejrzyste. CzöĈci sñ äatwe do zidentyfikowania, poniewaĔ ich nazwy
zawsze zaczynajñ siö od znaku podkreĈlenia. Na przykäad, moĔna stworzyè plik app/views/
chapter2/_person.rhtml
 zawierajñcy:

<p><%= person.name %></p>

Z gäównego szablonu moĔna by byäo zaäñczyè takñ czöĈè:

<%= render :partial => "person" %>

Jest  trochö  magii  wplecionej  w  przekazywanie  zmiennych  do  czöĈci.  PoniewaĔ  ta  czöĈè  jest
nazwana „person”, gäówny szablon bödzie szukaä zmiennej instancji 

@person

 i przekazywaä jñ

do czöĈci jako zmiennñ lokalnñ 

person

. Co jeĈli przykäadowa zmienna nie pasowaäaby do na-

zwy czöĈci? Wtedy trzeba jñ przekazaè jawnie jak tu:

<%= render :partial => "person", :locals => { :person => @adrian } %>

Wszystkie pary klucz – wartoĈè w tablicy asocjacyjnej 

:locals

 bödñ dostöpne jako zmienne

lokalne czöĈci.

DoĈè czöstym zastosowaniem czöĈci jest przeglñdanie tablicy obiektów i generowanie czöĈci
dla kaĔdego obiektu. Metoda 

render

 sprawia, Ĕe jest to proste dziöki opcji 

:collection

. Na

przykäad:

<%= render :partial => "person", :collection => @people %>

background image

Czytaj dalej...

38

_

Rozdzia

ĥ 2. Pierwsze kroki

W tym przykäadzie gäówny szablon zawiera tablicö 

@people

, która bödzie przeglñdana, a kaĔdy

element tablicy — zmienna lokalna 

person

 — zostanie przekazany do czöĈci.

DomyĈlnie szablony czöĈci powinny znajdowaè siö w tym samym katalogu co szablon gäówny.
Aby wykorzystaè czöĈci z poziomu innych kontrolerów, wystarczy dodaè nazwö katalogu jako
przedrostek. Na przykäad:

<%= render :partial => "chapter1/person" %>

Pomimo Ĕe gäównym szablonem jest chapter2/index.rhtml, czöĈè bödzie generowana na podstawie
pliku chapter1/_person.rhtml.

Pomocniki

Pomocniki  sñ  prostymi  metodami  Ruby  dostöpnymi  w  szablonach,  dostarczajñcymi  innego
sposobu na to, by szablon pozostaä czysty i czytelny. Dla kaĔdego kontrolera tworzony jest
jeden plik pomocnika, zatem 

Chapter2Controller

 bödzie powiñzany z plikiem app/helpers/

chapter2_helper.rb. JeĈli chce siö mieè pomocnika dostöpnego dla wszystkich kontrolerów, na-
leĔy zdefiniowaè go w application_helper.rb.

Rails  dostarcza  szereg  wbudowanych  pomocników,  które  sñ  powszechnie  uĔywane  —  wäaĈci-
wie juĔ widzieliĈmy kilka z nich. W czöĈci „Ukäad graficzny” powyĔej czwarty wiersz jest wy-
woäaniem pomocnika:

<%= javascript_include_tag "prototype" %>

javascript_include_tag()

 jest metodñ Ruby zdefiniowanñ przez Rails, która pobiera jako ar-

gument äaþcuch znaków (albo tablicö äaþcuchów znaków) i zwraca fragment HTML, jak np.:

<script src="/javascripts/prototype.js" type="text/javascript"></script>

Innym uĔytecznym pomocnikiem jest 

h

, który zamienia HTML na czysty tekst. Na przykäad,

<%= h @foo %>

 zapobiegnie zwróceniu znaków specjalnych HTML w wyjĈciu, zamieniajñc je na

encje, co jest waĔnym posuniöciem ze wzglödów bezpieczeþstwa przy wyĈwietlaniu danych
wprowadzonych  przez  uĔytkownika.  Implikacjö  tö  bödziemy  rozwaĔaè  dokäadniej  w  roz-
dziale 8.

Byè moĔe najczöĈciej uĔywanym pomocnikiem jest 

link_to

, który w prosty sposób generuje

äñcze. Na przykäad:

<%= link_to "Kliknij tutaj", :url => "/chapter2/myresponse" %>

Ten pomocnik zwraca: 

<a href="/chapter2/myresponse">Kliknij tutaj</a>

.

Jest to caäkiem trywialny przykäad, ale interesujñcñ sprawñ jest to, Ĕe zamiast przekazywania
zwykäego adresu URL jako parametru moĔna przekazaè nazwö kontrolera, nazwö akcji i inne
parametry  —  a  URL  zostanie  odpowiednio  skonstruowany.  Wspaniaäe  tutaj  jest  to,  Ĕe  gdy
zmienia  siö  ĈcieĔki  aplikacji,  äñcza  automatycznie  zostanñ  zmienione  tak,  aby  pasowaäy  do
zmienionych ĈcieĔek.

<%= link_to "Kliknij tutaj", :action => "myresponse" %>

WyjĈcie tej wersji jest takie samo jak powyĔej. Proszö zauwaĔyè, Ĕe nie okreĈlaliĈmy nazwy kon-
trolera — zostaäa ona pominiöta. Rails domyĈla siö, Ĕe chcemy uĔyè tego samego kontrolera,
w którym wäaĈnie siö „znajdujemy”.