11

noir webappを作成していますが、新しいビューとモデルを動的に作成する必要があります。リソースのビューとコントローラーが別々の名前空間を持っているnoirの例に従ってきましたが、これは非常にクリーンなアプローチであることがわかりました。

これに合わせて、ビューとモデルに対応する新しい名前空間を動的に作成し、それらに適切な関数をインターンできるようにする必要があります。私のアイデアは、新しい名前空間で呼び出されたときに適切なルート/部分/その他を提供する別の名前空間でマクロを指定することでした。

たとえば(私の最初のdefmacroを許してください):

(ns project.views.proto
  (:use noir.core
        hiccup.core
        hiccup.element
        hiccup.form))

(defmacro def-all-page
  [path]
  `(defpage ~path []
     (html
      [:h1 "Ya'll here"])))

から呼び出されます...

(ns project.proto
   (:use [clojure.contrib.with-ns :only [with-ns]])

(create-ns 'foo)
(intern 'foo 'path "path")  ; In reality, the path is dynamic which is why I intern it
(with-ns 'foo
    (clojure.core/refer-clojure)
    (use 'noir.core
         'hiccup.core
         'hiccup.element
         '[project.views.proto :only [def-all-page]])

    (def-all-page path)

ただし、新しい名前空間内からこれを呼び出すと、NullPointerExceptionが発生します。助けていただければ幸いです。より良いアプローチがあるかどうか。同様に、必要なすべての定義を含む名前空間にreferを使用するだけですか?

最初の投稿、そして私はそれがこれの繰り返しではないと思います。ありがとう!

4

1 に答える 1

1

まず第一に、この質問は少し時代遅れになっています。NoirとClojureはどちらも昨年進化してきました。わかりやすくするために、方程式からNoirを取り除き、マクロを使用して関数を動的に作成することについての質問に答えてみます。

REPLでフォローしてください:

$ lein repl
user=> (in-ns 'foo)
#<Namespace foo>
foo=> (clojure.core/refer-clojure)
nil
foo=> (defmacro say-hello-to
 #_=>           [name]
 #_=>           `(defn ~(symbol (str "hello-" name))
 #_=>                  []
 #_=>                  ~(str "hello: " name)))
#'foo/say-hello-to

ここでは、「hello-yourname」関数を定義するためのマクロを含む名前空間「foo」を作成します。別の名前空間を作成しましょう:

foo=> (in-ns 'bar)
#<Namespace bar>
bar=> (clojure.core/refer-clojure)
nil
bar=> (refer 'foo :only '[say-hello-to])
nil
bar=> (say-hello-to "tom") 
#'bar/hello-tom
bar=> (say-hello-to "jerry") 
#'bar/hello-jerry

これらが実際に機能するかどうかを見てみましょう。

bar=> (hello-tom)
"hello: tom"
bar=> (hello-jerry)
"hello: jerry"

これはあなたの元の例にかなり近いと思います。

お役に立てれば!

于 2013-10-27T22:33:26.950 に答える