Parte 1: Prima di tutto affrontare la sintassi al curry:
withUser
è un metodo che accetta una funzione curry f
di tipo User => Request[AnyContent] => Result
. Prende un oggetto User
e restituisce un'altra funzione che accetta uno Request
e restituisce un Result
. Scomponendola, se f
è che la funzione allora:
val g = f(user) // g is a function
val result = g(request) // returns a result
// same as:
val result = f(user)(request)
In pratica f
è proprio come una funzione che prende due parametri, ma invece di chiamare f(a, b)
si chiama f(a)(b)
.
withAuth
è anche un metodo che accetta una funzione al curry. Ha quasi lo stesso tipo di withUser
.
Parte 2: Ora come si fa a utilizzare gli stessi metodi:
Come spiegato here, il gioco fa si è definito la logica dell'applicazione dicendo è come trasformare gli oggetti in Request
Result
oggetti.
withAuth
è una funzione di supporto che si occupa dell'autenticazione per te e recupera comodamente il nome utente. Quindi lo si utilizza in questo modo:
def index = withAuth { username => implicit request =>
Ok(html.index(username))
}
Si restituisce una funzione che prende un Request
e restituisce un Result
, che è quello che gioca esigenze. Ma ciò che serve è una funzione al curry (che accetta un nome utente) e restituisce una funzione (che accetta una richiesta). Il parametro di richiesta è contrassegnato come implicito in modo che possa essere trasmesso implicitamente a qualsiasi chiamata di funzione/metodo che richiede un parametro di richiesta implicito. Ai fini di questa spiegazione, ignora semplicemente la parola chiave implicit
.
Parte 3: Traduzione di withUser
Beh, la sua firma è simile a withAuth
e l'obiettivo è per essere usato nello stesso modo, tranne il primo parametro sarà una User
invece di un String
. Quindi deve prendere un User => Request => Result
. La caratteristica richiesta richiede un parametro di tipo che indica il tipo del suo contenuto. Qui è AnyContent
. Quindi il tipo corretto per l'argomento di withUser
è User => Request[AnyContent] => Result
.Ciò significa che sarà in grado di utilizzare in questo modo:
withUser { user => implicit request =>
// do something with user and request to return a result
}
Se si guarda alla definizione di withUser
, tutto ciò che fa è chiamare withAuth
:
def withUser(f: User => Request[AnyContent] => Result) = withAuth {
// ...
}
Quindi tornerà lo stesso tipo come withAuth
significa che restituirà una funzione che trasforma un Request
in un Result
(vedere la Parte 2 sopra). Il che significa che saremo in grado di utilizzare in questo modo:
def index = withUser { user => implicit request =>
Ok(html.index(user))
}
Ciò che è passato come argomento di withAuth
è una funzione curry. Ho introdotto l'intermedio val
in modo da poter seguire i seguenti tipi:
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))
Non so perché stai ottenendo voti per chiudere la domanda. Penso che la tua domanda sia perfettamente legittima. Mi ero già visto quel codice prima e mi chiedevo come funzionasse. – huynhjl