sobota, 23 marca 2013

Programowanie webowe w Haskellu cz. 3

Trochę ostatnio zaniedbałem bloga za co bardzo przepraszam. Dzisiaj tematem będą własne bardziej wyrafinowane znaczniki w szablonach. Postaramy się wykonać znacznik <if>, który będzie działał według poniższej koncepcji.

Koncepcja

Pomysł polega na tym aby w szablonie móc wpisać coś takiego:
<if>
<equal a="${name}" b="kogut"/>
<then><b>My name is kogut</b></then>
<else>My name is not kogut</else>
</if>
<if>
<not><equal a="${name}" b="kogucik"/></not>
<then><b>My name is not kogucik</b></then>
<else>My name is kogucik</else>
</if>


Wydaje mi się, że koncepcja jest w miarę jasna. Po prostu jeżeli w pierwszym ifie ${name} będzie równe "kogut" to na stronie pojawi się My name is kogut, a w przeciwnym razie "My name is not kogut". Drugi natomiast wyświetli My name is not kogucik jeżeli ${name} będzie różne od "kogucik". Inaczej dostaniemy "My name is kogucik".

Funkcja addSplices

Aby dodać znaczniki, które będą rozpoznawalne we wszystkich szablonach potrzebujemy użyć funkcji addSplices. Podobnie jak funkcja renderWithSplices przyjmuje on listę par ("nazwa znacznika", wartość). Tą wartością tym razem będzie specjalnie przez nas przygotowana funkcja analizująca nieco znaczniki wewnątrz naszego znacznika "if". Zatem dopisujemy w pliku Site.hs w funkcji app, gdzieś przed funkcją return taką oto treść:
addSplices [("if", ifSplice)]

Jako, że za chwilę utworzymy sobie nowy plik o nazwie Splices.hs to od razu możemy go tutaj zaimportować. W tym celu na górze pliku, w miejscu gdzie występują instrukcje import dopisujemy:
import Splices

Nowe znaczniki

Jak wspomniałem już wcześniej utwórzmy sobie plik o nazwie "Splices.hs". Jego treść, którą za chwilę omówię będzie wyglądać następująco:


Najważniejszą funkcją w tym pliku jest ifSplice. Działa ona następująco:
  • najpierw pobieramy wszystkie dzieci elementu "if", przetwarzając dodatkowo elementy "not" i "equal" (gdyby się one tam znalazły) odpowiednimi funkcjami - to realizuje właśnie funkcja runChildrenWith,
  • następnie sprawdzamy czy w ogóle jakieś dzieci występują (po podmianie znaczników "equal" i "not"),
  • jeżeli nie to wyświetlamy komunikat błędu,
  • w przeciwnym razie pobieramy pierwszy element wewnątrz "if" i sprawdzamy czy jest to zwyczajny tekst,
  • jeżeli nie to znów wyświetlamy komunikat błędu, gdyż oczekujemy, że pierwszy element będzie równy "1" lub "0",
  • jak już mamy tekst to sprawdzamy czy jest równy "1",
  • jak tak to wyszukujemy element "then" i wyświetlamy jego dzieci,
  • jeżeli tekst jest różny od "1" to szukamy elementu "else" i wyświetlamy jego zawartość.

Funkcja equalSplice jest bardzo prosta. Pobiera ona znacznik "equal" (za pomocą funkcji getParamNode, która zwraca aktualnie przetwarzany znacznik, a wiemy, że jest nim "equal") i sprawdza czy istnieją argumenty o nazwie "a" i "b". Jeżeli tak to porównuje ze sobą zawartość obu argumentów i jeżeli są równe to zwraca tekst "1", a jeżeli nie to "0".

Funkcja notSplice również jest prostą funkcją. Najpierw pobiera swoje dzieci. Później sprawdza czy jest to dokładnie jeden element i to tekstowy. Jeżeli jest on równy "1" to zwraca "0", w przeciwnym razie zwraca "1". Tak na marginesie, w szablonie znacznik <not> może mieć wiele dzieci. Chodzi o to aby po podmienieniu wszystkich znaczników wewnętrznych pozostał tylko jeden. Podmianę zdefiniowanych znaczników wewnątrz elementu "not" realizuje funkcja runChildren. Dlatego właśnie możemy w szablonie umieścić <not><equal ... /></not>.

W tym momencie możemy już skompilować naszą aplikację, umieścić odpowiednie znaczniki w szablonie (np. te pokazane w koncepcji), uruchomić ją i nacieszyć oczy. Spróbujcie sobie w ramach ćwiczenia dopisać znaczniki "lt" i "gt" zwracające "1" odpowiednio, gdy argument a < argument b oraz dla drugiego znacznika, gdy argument a > argument b. W kolejnej części zajmiemy się obsługą bazy danych. To do następnego razu i powodzenia!

2 komentarze:

  1. Czy ten język jest jednym z bardziej funkcjonalnych w programowaniu webowym ?

    OdpowiedzUsuń