3

私は Web プロジェクトで noir を使用してきましたが、defpage マクロで定義されたすべての可能なルートへのアクセス レベル (およびサブレベル) に応じて、ユーザーへのアクセスを制限するところまで来ました。だからもともと持っていた

(defpage [:post "/mysite"] {:as input}
  (if-not (has-reqd-user-level? :levelX :sublevelY "/grantedRoute")
    (noir.response/redirect "/insufficientRights")
    ...))

そして、これで定型コードが取り除かれると思いました。

(defmacro defpage-with-user-level [level sublevel granted-route route data expr]
  `(defpage ~route ~data
     (if-not (has-reqd-user-level? ~level ~sublevel ~granted-route)
       (noir.response/redirect "/insufficientRights")
       ~expr)))

最後に、次のように使用します。

(defpage-with-user-level :levelX :sublevelY "/grantedRoute"
  [:post "/mysite"] {:as input}
  (html
    [:body [:h1 (str "Hello " (:name input) "!")]]))

しかし、Rich Hickey によるこの投稿 ( https://groups.google.com/forum/#!msg/clojure/4II-HKr_Pu0/2IcKit99cagJ ) で言及されているように、慣用的ではない位置バインディングのために少しぎこちなく感じます。既にマップが存在する場合。

しかし、マクロでの破壊バインディングの使用に関する例や議論を探していましたが、残念ながら、評価されていない式がずっと渡されていたため、それらの明確な使用法を見つけられませんでした。

そこで、次の解決策が頭に浮かびました。

(defmacro defpage-with-user-level [dts expr]
  `(defpage (:route ~dts) (:data ~dts)
     (if-not (has-reqd-user-level? (:level ~dts) (:sublevel ~dts) (:granted-route ~dts))
       (noir.response/redirect "/insufficientRights")
       ~expr)))

しかし今では、上記の例のように、ローカルを :get および :post からローカルにマップするデータ マップを渡す方法が明確ではありません。

最初の試行を改ざんせずにそのままにしておくのは正しいですか、それとも 2 番目のアプローチを使用する必要がありますか? ないことを願っています。他のオプションはありますか?私にお知らせください。

4

1 に答える 1

4

最初の解決策は問題ありません。Rich が話していたのは、データの型ごとに新しい型/クラスを作成するのではなく、単純な古いマップを使用してデータを渡すことでした。例: ユーザー データを表すクラスを作成するのではなく、単純なマップを使用してユーザー情報を表すことができます。

2回目の試みに関する限り、マクロでマップの構造化解除を次のように使用できます。

(defmacro defpage-with-user-level [{:keys [route data level sublevel granted-route]} expr]
  `(defpage ~route ~data
     (if-not (has-reqd-user-level? ~level ~sublevel ~granted-route)
       (noir.response/redirect "/insufficientRights")
       ~expr)))

(defpage-with-user-level {:level :levelX 
                          :sublevel :sublevelY 
                          :granted-route "/grantedRoute"
                          :route [:post "/mysite"] 
                          :data {:as input}}
  (html
    [:body [:h1 (str "Hello " (:name input) "!")]]))
于 2013-03-16T08:29:32.883 に答える