6

Clojure で appengine-magic を使用して Google App Engine データストアで動作するように、crud 関数のボイラープレートを生成しようとしています。以下で再現したモデルから値を生成する方法がわかりません。

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

私は appengine-magic にかなり慣れていませんが、データストアに入れて保存できるエンティティを定義できる防御機能を提供します! これにより、事前定義されたエンティティをデータストアに保存できます。

これらは次の形式を取ります。

(ds/defentity Post [title author])
(ds/save! (Post. title author))

まず始めに、次のように定義しました。

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

次のように呼び出します。

(list-entities *model*)

出力:

(Users. [:name :email :registered-on] Post. [:title :author])

現在、上記の出力を取得し、モデルに必要な数のエンティティを定義する ds/defentities を繰り返し呼び出す gen-entities を定義するのに苦労しています。

(defmacro gen-entities [entity fields]
  `(ds/defentity 'entity 'fields))

さらに、これがこの問題を解決するための合理的な方法であるとは確信していません。私はまだマクロに非常に慣れていないため、おそらくいくつかの間違いを犯しています。任意のヘルプ/明確さをいただければ幸いです。

ノート:

私が気付いたそのモデルは設計が不適切であり、以下のモデルははるかに優れています。

(def *model* {:users [:name :email :registered-on]
              :post [:title :author]})

ただし、マクロを書くという点ではより複雑なので、そのままにしておきます。

4

1 に答える 1

1

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

キーと値を互いにいじる必要はありません。インターリーブを使用してそれらを再び組み合わせるだけです。マップ上にマッピングすると、キーと対応する値が一度に得られます。

user=> (macroexpand-1 `(gen-entities ~model))
(do
  (ds/defentity Users [name registered-on email])
  (ds/defentity Post [title authour]))

注:これは、Varに保存されているモデルでは機能しません。の呼び出しでモデルを指定する必要がありますgen-entities

user=> (macroexpand-1 '(gen-entities model))
(
#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>
于 2011-05-08T12:45:29.910 に答える