Question

This is a lift webapp, visitor can view a topic by such url:

http://test.com/topic?id=12332

There is a topic.html and a TopicSnippet for it. I get the id in the snippet:

class TopicSnippet {
    val topic = S.param("id") match {
       case Full(id) => Topic.find(id) match {
          case Full(topic) => topic
          case _ => trigger 404, but how to ???
       }
       case _ => trigger 404, but how to ???
    }
}

You can see I want to trigger 404 in my snippet, but I don't know how to do it. I found somewhere it says we should check it in SiteMap, but that means I have to query db two times for a single topic -- one in SiteMap, one in snippet).

Is there any solution for this?

Was it helpful?

Solution

Instead of using the query parameter ?id, you could use Sitemap and Menu.param to accomplish what you are trying to do.

In Boot.scala add to Sitemap:

Menu.param[Topic]("Topic", "Topic", {
  id => Topic.find(id)
}, { _.id } ) / "topic" >> Title(t => t.name)

In Snippet, change constructor to:

class TopicSnippet(Topic topic) {
  // access topic as you need to
}

I made the above assumption that Topic had the fields id and name to illustrate how it might work, but that can obviously change. I also assume that Topic.find returns a Box.

What happens with the above is, you will access the url: /topic/12332 where 12332 is any id, and that param will be passed to the lookup you defined with Menu.param. That looked up value will then be passed to the TopicSnippet through the constructor. If the topic is not found (lookup returns Empty), a 404 will be returned to the browser. The >> Title() LocParam is not necessary, but will allow you to set the title of the page dynamically with the name of the topic.

From the user experience this makes a bit more sense too, since the 404 would be returned if the full url was not found. Using the query parameter, the page /topic would actually be found, it is just the lookup that is not.

If you need to use the query param approach, you could try to throw something like this which might work for you:

throw new ResponseShortcutException(() => new NotFoundResponse("Not Found")) 

OTHER TIPS

Would RequestVar solve your problem?

It can be used in the following way. Boot.scala:

    yourMenu >> If({ () =>
        val databaseInfo = "123" // work with the DB here
        if (good) {
            YourRequestVar.set(databaseInfo)
            true
        } else {
            false
        }
    }, "error")

something like the following in YourRequestVar.scala:

    object YourRequestVar extends RequestVar[String]("")

template:

        val databaseInfo: String = YourRequestVar.is
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top