Część 1: Najpierw niech zająć składnię nassza:
withUser
jest metodą, która zajmuje nassza funkcję f
typu User => Request[AnyContent] => Result
. Zajmuje obiekt User
i zwraca inną funkcję, która pobiera Request
i zwraca wartość Result
. Łamanie go, jeśli jest to funkcja f
następnie:
val g = f(user) // g is a function
val result = g(request) // returns a result
// same as:
val result = f(user)(request)
Praktycznie f
jest jak funkcję, która pobiera dwa parametry, ale zamiast dzwonić f(a, b)
zadzwonić f(a)(b)
.
withAuth
to również metoda, która przyjmuje funkcję curry. Ma prawie taki sam typ, jak withUser
.
Część 2: Teraz jak można korzystać z tych metod:
Jak wyjaśniono here, gra sprawia, że zdefiniowano logiki aplikacji, informując go, jak przekształcić Request
przedmiotów do Result
obiektów.
withAuth
to funkcja pomocnicza, która dba o uwierzytelnienie i wygodnie pobiera nazwę użytkownika. Więc go używać tak:
def index = withAuth { username => implicit request =>
Ok(html.index(username))
}
Zwraca funkcję, która pobiera Request
i zwraca Result
, która jest co grać potrzeb. Ale to, czego potrzeba, to funkcja curried (która przyjmuje nazwę użytkownika) i zwraca funkcję (która pobiera żądanie). Parametr żądania jest oznaczony jako niejawny, więc może zostać przekazany niejawnie do dowolnego wywołania funkcji/metody, który wymaga niejawnego parametru żądania. Na potrzeby tego wyjaśnienia zignoruj słowo kluczowe implicit
.
Część 3: Tłumaczenie withUser
Well, jego podpis jest podobna do withAuth
i celem jest, aby była ona używana w taki sam sposób, z wyjątkiem pierwszego parametru będzie User
zamiast String
. Więc musi wziąć User => Request => Result
. Właściwość żądania przyjmuje parametr typu, który wskazuje typ jego zawartości. Tutaj jest AnyContent
. Tak więc poprawny typ dla argumentu withUser
to User => Request[AnyContent] => Result
.Oznacza to, że będzie można go używać tak:
withUser { user => implicit request =>
// do something with user and request to return a result
}
Jeśli spojrzeć na definicję withUser
, wszystko robi to nazwać withAuth
:
def withUser(f: User => Request[AnyContent] => Result) = withAuth {
// ...
}
Więc zwróci ten sam typ jako withAuth
, co oznacza, że zwróci funkcję, która zamienia Request
w Result
(patrz część 2 powyżej). Co oznacza, że będziemy mogli go używać tak:
def index = withUser { user => implicit request =>
Ok(html.index(user))
}
Co jest przekazywana jako argument withAuth
jest curry funkcja. Wprowadziłem półprodukt val
, dzięki czemu można śledzić typy:
username => // first param is the username as a String
implicit request => // second param is the request
// here we have to return a Result...
// we lookup the user - we may not have one:
val userOption: Option[User] = UserDAO.findOneByUsername(username)
// f is the code block that will be provided inside withUser { f }
// Part 1 explains the f(user)(request) syntax
// We call f to get a result, in the context of the Option monad
val resultOption: Option[Result] = userOption.map(user => f(user)(request))
// if we have a result, return it; otherwise return an error.
resultOption.getOrElse(onUnauthorized(request))
Nie wiem, dlaczego dostajesz głosy, aby zamknąć pytanie. Myślę, że twoje pytanie jest całkowicie uzasadnione. Już wcześniej widziałem ten kod i zastanawiałem się, jak to działa. – huynhjl