poniedziałek, 14 kwietnia 2014

Warsztaty z Play i ciekawostki ze Scali

Zamiast zastanawiać się jak zacząć ten wpis aby oddać jak szczęśliwy jestem, że warsztaty udało się doprowadzić do skutku i spotkały się one z moim zdaniem dużym zainteresowaniem - użyję cudzej pracy i dam link do relacji Krzysztofa Telki z warsztatów

FoldLeft wszyscy szybko załapali

I z pisaniem testów też nie było problemów.

Tu jest reszta fotek:

Kolejne spotkania

Drugą edycję wprowadzenia będę chciał zrobić pomiędzy majówką a Geeconem. Na retro były prośby o więcej zadań - także zacząłem przygotowywać plan zajęć (a być może nawet i go skończyłem)

Jak ktoś ma sugestie niech śmiało zapodaje. Później po Geeconie a przed 33Degree (konferencje to dobry punkt odniesienia w czasie bo mogę zaplanować kiedy będę trzeźwy) zorganizuję jakoś drugi moduł "Obsługa formularzy, parsery requestów i kompozycja Akcji".

Layouty w Playu

W trakcie warsztatów pojawiło się pytanie, na które już umiem odpowiedzieć : "czy da się zrobić tak layouty aby dany tail nie wiedział w jakim szablonie jest używany".
O co chodzi : Play domyślnie wygeneruje nam szablon z rozwiązaniem "tail wywołuje szablon"

@main("Naglowek") {

 <h1>Moj tail</h1>


}
Jako że szablony to zwykłe funkcje to można też w drugą stronę : "wywołać taila z szablonu"
To źródło jest footer.scala.html
@import play.api.Play.current
<footer>
Revision @current.configuration.getString("application.revision")
</footer>
A to już wywołanie w szablonie
 <body>
        @content
        @footer()
 </body>
Proste?Proste.

Ciekawy przykład z życia

Na jednym ze spotkań firmowych dyskutowaliśmy sobie po co robić w deklaracji funkcji kilka par nawiasów i co dobrego z tego może wyjść. Wymyśliliśmy sobie funkcję "policjanta", która sprawdza czy dany user może wykonać jakąś tam operację :

def withProperAccess(user:User)(operation:User=>String)={
  if(user.securityLevel>2) operation(user) else "sorry ziom"
 } 
I teraz aby nawiązać do jakiejś formy dependency injection stworzymy funkcję, która z kontekstu wstrzyknie usera i wyprodukuje funkcje jednoelementową :
 def injectUser(function:(zagadka))={
   val contextUser=User("Roman",3)
   function(contextUser)
  } 
I tutaj pojawiła się zwiecha - jaki właściwie typ ma oryginalna funkcja dwuargumentowa, która jeszcze jako jeden z parametrów przyjmuje funkcje?(czyli co tam w ten nawias (zagadka) wstawić)

Okazuje się, że ów typ to : User=>(User=>String)=>String I teraz ktoś kto to widzi po raz pierwszy w życiu może zareagować niezwykłym zdumieniem wypływającym z silnego zderzenia jego obecnego pojęcia świata z napotkanym kształtem: Ewentualnie w twojej głowie może zabłysnąć niecodzienne zdziwienie wywołane kontrastującym konfliktem pomiędzy zmysłami a doświadczeniem:
A niepotrzebnie bo wyjaśnienie jest proste.

Co to jest?

Zaczynamy od strony lewej User=>(User=>String)=>String
Generalnie to co jest po lewej stronie strzałki to to co funkcja dostanie jako argument a to co po prawej (jak dziwne by nie było) to to co zwróci. Tutaj po stronie lewej jest User i to jest właśnie to magiczne wstrzykniecie usera z kontekstu - function(contextUser) i w wyniku dostajemy to po prawej.

Mamy teraz to coś : (User=>String)=>String i znowu to co jest po lewej to argument ale tym razem argument ma też strzałkę w sobie - bo toż to funkcyja jest ino. Argumentem jest funkcja, która przyjmuje Usera a zwraca String czyli np :

val funkcjaBiznesowa=(user:User)=>secretKeys.getOrElse(user.name, "nima")
Zaś wywołanie funkcji
(User=>String)=>String
Wygląda tak :
 val securityAccesWithUserInjected=injectUser(withProperAccessFun)
securityAccesWithUserInjected(funkcjaBiznesowa)

Mam nadzieję, że teraz jest trochę jaśniej.

*               *              *

Brak komentarzy:

Prześlij komentarz