Это правильный способ обработки RESTful, как URL в Lift Framework? - PullRequest
3 голосов
/ 10 января 2010

Если у меня есть URL-адрес типа http://localhost/Test/edit/{id}, и я хотел бы преобразовать {id} в параметр вместо части пути URL-адреса.

Это лучший способ сделать это, создав меню с RewriteRequest? Потому что я нашел небольшой пример, если у меня есть много шаблонов URL, как это.

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")) -> ()

    })
})

Ответы [ 5 ]

3 голосов
/ 10 января 2010

В вашем boot.scala вам нужно следующее (из реального рабочего кода!) Обратите внимание, что каждый путь RewriteResponse должен быть в вашей карте сайта.

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))
}
2 голосов
/ 15 июня 2010

Я наткнулся на этот пост, потому что у меня был тот же вопрос. Ответ Джима Барроуса правильный (и самый простой), но без объяснения мне было трудно понять, что делает этот код. Подробное объяснение того, почему решение Jim работает, можно найти в онлайн-книге Lift (http://groups.google.com/group/the-lift-book)., см. Раздел 3.12, озаглавленный «Перезапись URL-адреса»), в котором шаг за шагом рассказывается, как создать URL-адрес RESTful.

В любом случае, не нужно писать собственный Loc для достижения желаемого эффекта.

Удачи!

2 голосов
/ 10 января 2010

Спасибо за все ваши ответы.

Что мне больше всего нужно, так это то, что эти вещи переписаны в тесном сочетании с Menu, чтобы я мог настроить их только в моем классе Model, например, CRUDify trait.

В конце концов, я сам создал подкласс Loc для обработки этих правил перезаписи, и обнаружил, что он работает довольно хорошо и делает вещи намного проще (по крайней мере для меня), поэтому я публикую код здесь.

Не стесняйтесь копировать это, если кому-то это нужно

/**
 *  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) -> ()
        }
    })
}
1 голос
/ 10 января 2010

Извините, вышеприведенный комментарий немного грязный.

Проблема в том, что если у меня есть шаблон с именем edit.html в webapp / Test, который я использую для редактирования элемента.

И у меня есть экземпляр меню, подобный следующему:

Menu (Loc("Test", List("Test") -> true, "Test"))

Это будет соответствовать только URL-адресу как http://localhost/Test/edit,, а не как http://localhost/Test/edit/1

0 голосов
/ 10 января 2010

Почему вы хотите изменить его на параметр запроса? Это по техническим или базовым причинам?

На мой взгляд, {id} относится к пути URI, он идентифицирует уникальный ресурс, и мне нравится хранить эту информацию внутри пути. URI могут быть символьной строкой любого типа (поэтому параметр запроса также будет работать), но я бы смоделировал URI как можно ближе к идентификатору ресурса.

...