Search code examples
scalalift

How can I check if a URL matches an existing Loc in Lift?


I'm attempting to build some fairly complex breadcrumb functionality into my application where multiple pages may link to a detail page, but I only want to display the detail page's breadcrumbs if the page is reached through a specific route.

In my use case, a user would go to the search page and type in a search string. The form uses a "get" method on the current page to render a search result with some items for the user. The user selects an item to dive into it's detail page. On the detail page, I check S.referer and find that it is a string: http://localhost:8080/myapp/search?q=Query+Data+Here.

Is there any way that I could take the Search page Loc and test if the above String URL matches it? Right now I'm performing this check by simply running a contains on the reference string and doing behavior based on the outcome.

Here is my current implementation:

/**
 * List of valid pages to use for generating the page breadcrumbs.
 */
private def validParentLocations = Seq("Search", "Browse")

/**
 * If the referer to this page is one of the valid parent locations,
 * then find the a tag with the "prev" id and route it to the referer.
 *
 * If the referer to this page is not in the list or empty, do not
 * display the breadcrumb component.
 */
def breadcrumb = {
  S.referer match {
    case Full(reference) =>
      validParentLocations.find(s => reference.contains(s"myapp/${s.toLowerCase}")).map(parent =>
        "#prev *" #> parent &
        "#prev [href]" #> reference
      ).getOrElse(ClearNodes)
    case _ => ClearNodes
  }
}

As you can see, I'm hoping to replace the validParentLocations to be Loc's instead of flimsy Strings that might break if I ever modify a page's definition in the Boot. Is there some way to basically say myPageLoc.checkIfUrlMatches(string: String): Boolean or a match pattern that I'm missing? Is there a more elegant way to do this with existing functionality in Lift, or otherwise?


Solution

  • After toying around with this for a while I found a way to "register" a Loc to be a valid referrer to the Detail page by using a shared LocGroup name. Now I can grab all the valid referral Locs for the page and call their default href function to test if they match - Still feel like there might be a better way... Any referral link that matches mine in any capacity could be let through.

    Here's the code:

    Boot.scala:

    <...>
    Menu.i("Search") / "myApp" / "search" >> LocGroup("main", Detail.referralKey),
    Menu.i("Browse") / "myApp" / "browse" >> LocGroup("main", Detail.referralKey),
    Detail.getMenu,
    <...>
    

    Detail.scala:

    <...>
    def referralKey = "detail-page-parent"
    
    /**
     * Sequence of valid Locs to use for generating the page breadcrumbs.
     */
    private def validParentLocations = LiftRules.siteMap.map(site => site.locForGroup(locGroupNameForBreadcrumbParents)) openOr Seq()
    
    /**
     * If the referer to this page is one of the valid parent locations,
     * then find the a tag with the "prev" id and route it to the referer.
     *
     * If the referer to this page is not in the list or empty, do not
     * display the breadcrumb component.
     */
    def breadcrumb = {
      S.referer match {
        case Full(reference) =>
          validParentLocations.find(loc => reference.contains(loc.calcDefaultHref)).map(parent =>
            "#prev *" #> parent.name &
            "#prev [href]" #> reference
          ).getOrElse(ClearNodes)
        case _ => ClearNodes
      }
    }
    <...>