我一直在网络项目中使用黑色,我开始限制对用户的访问,这取决于他们对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撰写的这篇文章中提到的那样,由于位置绑定感觉有点尴尬,当已经存在地图时这不是惯用的。
但是,我一直在寻找关于在宏中使用解构绑定的一些例子或讨论,遗憾的是,我没有找到任何明确的使用它们,因为它的未经评估的表达式一直在传递。 / p>
所以,我想到了以下解决方案:
(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到本地,如上例所示。
我是否做得正确,让我的第一次尝试被篡改,或者我是否真的需要使用第二种方法?我希望不是。还有其他选择吗?请让我知道。
答案 0 :(得分:4)
你的第一个解决方案很好。 Rich谈论的是使用普通的旧地图传递数据,而不是为每种类型的数据创建新的类型/类。例如:您可以使用简单的地图来代替用户信息,而不是创建表示用户数据的类。
就您的第二次尝试而言,您可以在宏中使用地图解构:
(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) "!")]]))