Home > Grails, Groovy > Grails – kontrolery cz. 1

Grails – kontrolery cz. 1

Czas wrócić do zgłębiania wiedzy nt. Grails i pisania na ten temat. Powrót do Polski i cała masa innych rzeczy do zrobienia spowodował zapuszczenie blogów. Czas to zmienić :)

Teraz przyszedł czas na literkę C (MVC - M poznaliśmy przy GORMie, V będzie później).

Kontrolery w Grails zajmują się obsługą requestów. Kontroler to klasa zawierająca w nazwie Controller i umieszczona w odpowiednim katalogu (controllers ;-) ). Kontroler może wygenerować odpowiedź na nasze rządanie lub przekierować na widok (co to znaczy dowiemy się jak dobierzemy się do literki V).

Domyślnie nasze URI jest odpowiednio zmapowane na kontroler (konwencja ponad konfigurację). I tak URI /book/list jest zmapowane na kontroler BookController i akcję (metodę) list. Bardziej dociekliwi na pewno zerkną do katalogu conf do pliku UrlMappings.groovy i zobaczą, że jest mała konfiguracja, ale domyślna i jeśli nie ma potrzeby jej zmieniać, warto się jej trzymać (konwencja ponad konfigurację - cała esencja Grails (i nie tylko)).

A teraz bardzo ważna informacja: dla każdego żądania jest tworzona NOWA INSTANCJA kontrolera. Kontroler jest w związku z tym thread-safe. Ma to też konsekwencje jeśli chodzi o wystawienie danych dla warstwy widoku, ale o tym za chwilę.

Grails pozwala nam na zdefiniowanie właściwości defaultAction, która pozwala wskazać domyślną akcję w kontrolerze. Są też inne domyślne zachowania:

  • jeśli kontroler ma tylko jedną akcję, to staje się ona domyślną akcją
  • jeśli kontroler posiada akcję index (i inne) to akcja index automatycznie staje się domyślną
  • powyższe zachowanie można zmienić korzystając z defaultAction

W kontrolerze możemy skorzystać z "zakresów" (ang. scope). Scope jest bytem, do którego możemy zapisać różne wartości i w zależności od rodzaju, będzie miał on różną widoczność:

  • servletContext - zasięg całej aplikacji, dostępny wszędzie
  • session - odpowiadający sesji HTTP użytkownika
  • request - reprezentujący bieżące żądanie
  • params - reprezentujący parametry żądania
  • flash - request +1 :) Wszystko co zapiszemy w scope flash będzie dostępne podczas bieżącego żądania oraz w następnym żądaniu, po czym zostanie automatycznie wyczyszczone.

Myślę, że jest to w miarę jasne dla osób, które już miały kontakt z aplikacjami web. Flash można wykorzystać np. aby wyświetlić komunikat błędu po przekierowaniu.

Z grubsza już wiemy, jak pobrać dane z bazy (GORM) i gdzie to zrobić (kontroler). Nauczymy się dane wyświetlać przy literce V, ale jak te dane przekazać do widoku?

Jest na to kilka sposobów, najprostszy to zwrócenie modelu (czyli mapy zawierającej nasze dane) z akcji kontrolera.

def show = {
 	[ book : Book.get( params.id ) ]
}

Jeśli nie zwrócimy jawnie modelu, to zostaną użyte właściwości kontrolera (tutaj dokumentacja znowu wspomina o tym, że mamy nową instancję kontrolera na każde żądanie, więc jest to bezpieczne).

Jest jeszcze sposób z wykorzystaniem klasy Springa ModelAndView. Póki co zostawiam, prostsze rozwiązania narazie mi wystarczają :)

A jak wybierany jest widok? Surprise, surprise :) Konwencja. Jeśli jesteśmy w kontrolerze Book i akcji list, to zostanie wybrany widok grails-app/views/book/list.gsp. Oczywiście możemy skorzystać też z metody render i jawnie określić widok i przekazać model.

Możemy też wykorzystać metodę render to ręcznego stworzenia odpowiedzi, np. prostego tekstu, itp.

Ćwiczenie

W ramach nowej tradycji będę starał się do każdego posta w ramach utrwalenia dodawać małe ćwiczenie i pytania utrwalające wiedzę. Ćwiczenie na dziś:

Napisz kontroler, który w jednej z akcji wygeneruje linka do innej akcji tego kontrolera i dodatkowo przekaże parametr (zupełnie dowolny). W nowej akcji odczytaj go i zrób przekierowanie na następną akcję, ale tak, żeby nie zgubić wcześniej przekazanego parametru (jaki scope wybierzesz?). Dodaj jeszcze jedną akcję (nie index) i spraw, żeby stała się akcją domyślną.

Grails, Groovy

  1. Maj 22nd, 2009 at 06:19 | #1

    Ciekawy pomysł z tymi ćwiczeniami. Gdzie umieszczać rozwiązania do sprawdzenia? Kiedy rozwiązania, aby można było porównać moje z Twoim?

  2. Maj 22nd, 2009 at 16:56 | #2

    Hmm, szerze mówiąc to myślałem o tym, że każdy sam spróbuje rozwiązać ćwiczenie :) nie jest szczególnie trudne, ale pewnie pojawią się różne pomysły. Kod będzie dość krótki, więc rozwiązania mogą być tu w komentarzach :)

  1. Maj 27th, 2009 at 22:04 | #1