A good way to stay flexible is to write less code. --Pragmatic Programmer

By , on June 8, 2011

Development, Scala

Tags: , , ,


As our website grows and people can log in, add books to their own collection, a need to access this collection on their mobile arises.

When starting the mobile application and entered the correct login information, a request is being made to get the list of authors.
Clicking on an author will get a list of books from that author that the user owns, clicking on a book shows the details.

So the first query that needs implementing is: Give me a list of Authors for which the current user owned books

Given the Following Mapper Data Model:
Author <- (1) -> Book <- (2) -> User
(1) An Author can have more books while books can be written by multiple authors (N-N)
(2) A user can own multiple books, while a book can have multiple owners (N-N)

note: When successfully authenticating in a user his API key is returned which is used in all other requests

Below we will see the code that executes this query
what happens line by line is this:

  • Line4: we get a list of books for the current user
  • Line5: we map the colllection to one that contains the authors for each book, the result is a list of lists of authors List[List[Author]]
  • Line6: foldLeft applies the method to each element in the list, from left to right, as the method ++ means adding two list’s together, we’ll end up with one list containing all authors
  • Line7: distinct removes any duplicates in there
  • Line8: We sort the list on the author’s lastName property
  • Line9: we map it to a List of Xml fragments

Scala’s inline XML support allows us to simple put the Authors tag around it.
The second case does the same but gives a JSON response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
serve {
  case "api" :: key :: "user" :: "authors" :: "all" :: _ XmlGet _ => {
    <Authors> {
      Book.findAll(In(Book.id ,BookUser.book, By(BookUser.user, getUserIdFromKey(key))))
        .map(book => { book.authors.get })
        .foldLeft(List[Author]())(_ ++ _)
        .distinct
        .sortWith((a1:Author, a2:Author) => a1.lastName.is < a2.lastName.is)
        .map(author => author.toXml)
      }
    </Authors>
  }
  case "api" :: key :: "user" :: "authors" :: "all" :: _ JsonGet _ => {
    JsonWrapper ("Authors", {
      Book.findAll(In(Book.id ,BookUser.book, By(BookUser.user, getUserIdFromKey(key))))
        .map(book => { book.authors.get })
        .foldLeft(List[Author]())(_ ++ _)
        .distinct
        .sortWith((a1:Author, a2:Author) => a1.lastName.is < a2.lastName.is)
        .map(author => author.toJson)
      })
  }
}
 
//helper method
def getUserIdFromKey(key:String):Long = {
  User.find(By(User.key, key) match {
    case Full(user) => user.id
    case (_) => 0 
  }
}


Comments are closed.