too*_*ays 6 macros clojure appengine-magic google-cloud-datastore
我特意尝试使用Clojure中的appengine-magic为crud函数生成样板,以便与Google App Engine数据存储区一起使用.我很难弄清楚如何从我在下面复制的模型中生成值.
(def *model* {:users [{:name "Adam"
:email "adam@gmail.com"
:registered-on "07-05-2011"}
{:name "Greg"
:email "gregory@gmail.com"
:registered-on "11-05-2011"}]
:post [{:title "A"
:authour "Adam"}
{:title "B"
:author "Greg"}]})
Run Code Online (Sandbox Code Playgroud)
我对appengine-magic相当新,但是它提供了一种不确定性,允许你定义可以放入数据存储区并保存的实体!它允许您将预定义的实体保存到数据存储区中.
采取以下形式:
(ds/defentity Post [title author])
(ds/save! (Post. title author))
Run Code Online (Sandbox Code Playgroud)
现在我要定义:
(defn list-entities [model]
"Takes a representation of the model and lists the entities in preparation for generating defentities"
(interleave (vec (map first (partition 1 (map (comp symbol capitalize #(str % ".") name) (keys model)))))
(map vec (map keys (map first (vals model))))))
Run Code Online (Sandbox Code Playgroud)
用它来调用:
(list-entities *model*)
Run Code Online (Sandbox Code Playgroud)
输出:
(Users. [:name :email :registered-on] Post. [:title :author])
Run Code Online (Sandbox Code Playgroud)
现在我很难定义生成实体,它将采用上面的输出并反复调用ds/defentities定义与我的模型所需的实体一样多的实体.
(defmacro gen-entities [entity fields]
`(ds/defentity 'entity 'fields))
Run Code Online (Sandbox Code Playgroud)
此外,我无法确定这是解决此问题的合理方法.我仍然是非常新的宏,可能犯了几个错误.任何帮助/清晰度将不胜感激.
注意:
我已经意识到的那个模型设计得很糟糕,下面的模型要好得多:
(def *model* {:users [:name :email :registered-on]
:post [:title :author]})
Run Code Online (Sandbox Code Playgroud)
然而,在编写宏方面它更复杂,所以我将保持原样.
我认为宏是必需的,因为defentity似乎定义了一种类型。
(defmacro gen-entities
[model]
`(do
~@(for [[entity-kw values] model]
(let [entity-sym (-> entity-kw name capitalize symbol)
fields (map (comp symbol name) (keys (first values)))]
`(ds/defentity ~entity-sym [~@fields])))))
Run Code Online (Sandbox Code Playgroud)
您不必相互干扰键和值,只需通过交错将它们再次组合在一起即可。在地图上进行映射将一次性为您提供键和相应的值。
user=> (macroexpand-1 `(gen-entities ~model))
(do
(ds/defentity Users [name registered-on email])
(ds/defentity Post [title authour]))
Run Code Online (Sandbox Code Playgroud)
注意:这不适用于存储在 Var 中的模型。您必须在调用中指定模型gen-entities。
user=> (macroexpand-1 '(gen-entities model))
(
#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>
Run Code Online (Sandbox Code Playgroud)