Faber
Faber

Reputation: 380

Functions as parameters using scala syntax

I'm relatively new to functional programming in scala. I came across the flowing method. I have been unable to figure out exactly what it is doing?

def getPostsByFilters = (authenticatedPublicApiPostArticleAction andThen rateLimitedApiAction).async(BodyParsers.parse.tolerantJson) { implicit request =>
    implicit val apiKey = Some(request.apiKey)
    request.body.validate[ArticlePostQuery] fold(
      errors => futureBadRequest(errors.toString()),
      articleQuery => verifyPostQueryParams(articleQuery, verifiedApiRequest => {
        val PostsNetwork = PostsNetwork(true, verifiedApiRequest.contentType, verifiedApiRequest.orderBy)
        apiArticleService.findApiArticlesWithPostRequest(verifiedApiRequest, PostsNetwork) map (articles => wrapUpResultsToJson(ApiPosts(articles)))
      }))
  }

It is in a play API controller and the method is mapped to a post request in the route file.

I know it take a json post request and returns a json response, but can someone explain what is actually happening and if there is a way to refactor it to make it more readable?

Upvotes: 0

Views: 52

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149608

Dislaimer: I am not familiar with this piece of code. My reply is an attempt to help decipher the method invocations in an attempt to help you understand it better.

This method seems to be doing a couple of things.

  1. Authentication and rate limiting - This is done by

    authenticatedPublicApiPostArticleAction andThen rateLimitedApiAction
    

    Note andThen is used for composing functions from left to right. So first authentication is being done, and then rate limiting

  2. Asynchrnous JSON parsing:

    async(BodyParsers.parse.tolerantJson)
    

    Attempts to parse the body of the HTTP requests as a JSON regarding the passed in Content-Type header.

  3. Validation of the body:

    request.body.validate[ArticlePostQuery]
    

    This appears to be validating the body (JSON) matches the structure of ArticlePostQuery (which I assume is a case class). The validate method returns a JsResult, which is an ADT (Algebraic Data Type), which may be either JsSuccess or JsError. The fold method is used to handle both the error case (the first function) or the success case (second function).

  4. Acting upon result:

    If the former happens, the API returns an error status code (I assume some sort of 400 bad request with the error:

    errors => futureBadRequest(errors.toString())
    

    If the latter happens it attempts to verify that all query parameters exist:

    articleQuery => verifyPostQueryParams(articleQuery, verifiedApiRequest
    

    If they do exist, it invokes the following thunk:

    val PostsNetwork = 
      PostsNetwork(
        true, 
        verifiedApiRequest.contentType, 
        verifiedApiRequest.orderBy
      )
    
    apiArticleService
      .findApiArticlesWithPostRequest(verifiedApiRequest, PostsNetwork) 
      .map(articles => wrapUpResultsToJson(ApiPosts(articles)))
    }))
    

    To retrieve the article posts. Then, it maps over the result to return a JSON result from an ApiPosts object.

Upvotes: 2

Related Questions