これは、リフトフレームワークでRestfulのようなURLを処理する正しい方法ですか?

StackOverflow https://stackoverflow.com/questions/2036037

  •  19-09-2019
  •  | 
  •  

質問

URLがある場合 http:// localhost/test/edit/{id}そして、{id}は、URLパスパーツの代わりにパラメーターに変換したいです。

書き直してメニューを作成することでそれを行う最良の方法ですか?このようなロット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")) -> ()

    })
})
役に立ちましたか?

解決

boot.scalaでは、次の(実際の作業コードから!)が必要です。各書き込みパスはサイトマップにある必要があることに注意してください。

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))
}

他のヒント

すべての返信をありがとう。

私が一番欲しいのは、これらがメニューとしっかりと組み合わせたものを書き直しているので、Crudify特性のようにモデルクラスだけでそれらをセットアップできることです。

最終的に、私はこれらの書き換えルールを処理するために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) -> ()
        }
    })
}

同じ質問があったので、私はこの投稿に出くわしました。ジム・バロウズからの答えは正しい(そして最も簡単な)が、説明がなければ、そのコードが何をしているのかを把握するのは難しいことでした。ジムのソリューションが機能する理由の詳細な説明は、リフトブックオンラインで見つけることができます(http://groups.google.com/group/the-lift-book)。 「URL書き換え」というタイトルのセクション3.12をご覧ください。

とにかく、目的の効果を達成するためにカスタムLocを作成する必要はないはずです。

幸運を!

申し訳ありませんが、上記のコメントは厄介な厄介です。

問題は、edit.htmlという名前のテンプレートがWebApp/テストの下にある場合、アイテムの編集に使用するテンプレートであることです。

そして、私は次のようなメニューインスタンスを持っています:

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

それはurlのようにのみ一致します http:// localhost/test/edit, 、似ていません http:// localhost/test/edit/1

なぜそれを変更してパラメーションを照会したいのですか?それは技術的な理由ですか、それともフレームワークの理由ですか?

{id}は、URIパスの私の見解に属し、一意のリソースを識別し、この情報をパス内に保持するのが好きです。 urisは、あらゆる種類の文字文字列になります(クエリパラメーターも機能します)が、URIを可能な限り近いリソースIDにモデル化します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top