É essa maneira correta de lidar com RESTful como URL na estrutura de elevador?
Pergunta
Se eu tenho um URL como http: // localhost/test/edit/{id} e eu gostaria que o {id} se transforme em um parâmetro em vez da parte do caminho do URL.
É a melhor maneira de fazer isso criando um menu com rewriterequest? Porque eu achei um pouco de caldeira se eu tiver muito padrão de URL como esse.
val menu = Menu(new Loc[Unit] {
override def name = "Test"
override def text = "Test"
override def link = (List ("Test"), true)
override def params = Nil
override def defaultValue = Full(())
def isTarget (path: ParsePath) = path match {
case ParsePath (List("Test", "edit", id), _, _, _) => true
case _ => false
}
override def rewrite = Full ( NamedPF("Test") {
case RewriteRequest (path, _, _) if isTarget(path) =>
RewriteResponse(List("Test", "edit"),
Map("id" -> "1024")) -> ()
})
})
Solução
No seu boot.scala, você precisa do seguinte (a partir do código de trabalho real!) Observe que cada caminho de reescritor de resposta deve estar no seu sitemap.
LiftRules.rewrite.append {
case RewriteRequest(ParsePath(List("shopInfo", "view", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "view" :: Nil, Map("id" -> id))
case RewriteRequest(ParsePath(List("shopInfo", "orders", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "orders" :: Nil, Map("id" -> id))
case RewriteRequest(ParsePath(List("shopInfo", "sync", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "sync" :: Nil, Map("id" -> id))
case RewriteRequest(ParsePath(List("shopInfo", "delete", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "delete" :: Nil, Map("id" -> id))
case RewriteRequest(ParsePath(List("shopInfo", "edit", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "edit" :: Nil, Map("id" -> id))
}
Outras dicas
Obrigado por todas as suas respostas.
O que eu mais quero é que essas coisas reescrevem bem combinadas com o menu, para que eu pudesse configurá -las apenas na minha aula de modelo, como a característica crudificada.
No final, criei uma subclasse do LOC para lidar com essas regras de reescrita e achei que funciona muito bem e tornar as coisas muito mais simples (pelo menos para mim), então posto o código aqui.
Sinta -se à vontade para copiar isso se alguém precisar
/**
* A RESTful-like URL handling Loc
*
* If you have the following templates:
*
* * webapps/item/edit.html
* * webapps/item/view.html
*
* You want the following URL map to corresponding template with
* last path component as a S parameter.
*
* http://localhost/item/edit/1 to http://localhost/item/edit
* http://localhost/item/view/1 to http://localhost/item/view
*
* You could create a Menu with this Loc class in your Model object.
*
* <code>
* object Item extends Item with LongKeyedMetaMapper[Item]
* {
* // Other methods here...
*
* def menu () {
*
* // What methods do we have?
* val methods = List ("view", "edit")
*
* val parameterName = "itemID"
* val itemLoc = new RESTfulLoc("Item", List("item"), "Item",
* methods, parameterName)
*
* Menu (itemLoc)
* }
* }
* </code>
*
* Now add the menu to SiteMap in Boot.boot
*
* <code>
* class Boot {
* def boot () {
*
* val entries = Item.menu :: Nil
*
* LiftRules.setSiteMap(SiteMap(entries:_*))
* }
* }
* </code>
*
*
* Finally, You could access the parameter in your snippet with
* S.param("itemID")
*
*/
class RESTfulLoc (val name: String, val path: List[String],
val text: LinkText[Unit], val methods: List[String],
val parameterName: String,
val locParams: LocParam[Unit]*) extends Loc[Unit]
{
override val defaultValue = Full(())
override val params = locParams.toList
override val link: Link[Unit] = (List(path.first), true)
def this (name: String, path: List[String], text: LinkText[Unit],
methods: List[String], locParams: LocParam[Unit]*) =
{
this (name, path, text, methods, "id", locParams:_*)
}
private def isTarget (path: ParsePath) =
{
path.partPath -- this.path match {
case List (action, id) => {
(methods contains action) && id != "index"
}
case _ => false
}
}
override def rewrite = Full (NamedPF("RESTfulLoc")
{
case RewriteRequest (path, _, _) if isTarget(path) => {
val parameter = path.partPath.last
val action = path.partPath.init
val data = Map (parameterName -> parameter)
RewriteResponse(action, data) -> ()
}
})
}
Eu tropecei neste post porque tinha a mesma pergunta. A resposta de Jim Barrows está correta (e a mais fácil), mas sem nenhuma explicação, foi difícil para mim entender o que esse código está fazendo. Uma explicação detalhada de por que a solução de Jim funciona pode ser encontrada no Livro do Lift Online (http://groups.google.com/group/the-lift-book). Confira a Seção 3.12, intitulado "URL Rewriting", que o leva a passo a passo sobre como construir um URL repousante.
De qualquer forma, não deve haver necessidade de escrever um LOC personalizado para alcançar o efeito desejado.
Boa sorte!
Desculpe, o comentário acima é um Liitle bagunçado.
O problema é que, se eu tiver um modelo chamado Edit.html em WebApp/Test, que é o modelo que eu uso para editar um item.
E eu tenho uma instância de menu como o seguinte:
Menu (Loc("Test", List("Test") -> true, "Test"))
Só corresponderia ao URL como http: // localhost/teste/edição, nada como http: // localhost/test/edit/1
Por que você deseja alterá -lo para consultar param? É por razões técnicas ou de estrutura?
O {id} pertence à minha opinião ao caminho URI, identifica um recurso exclusivo e eu gosto de manter essas informações dentro do caminho. Os URIs podem ser qualquer tipo de sequência de caracteres (para que o parâmetro de consulta também funcionasse), mas eu modelaria os URIs o mais próximo possível do ID de recursos.