clutch-clojurescript's functionality has been folded into Clutch proper, so this project is deprecated.
Head over to Clutch to see how you can write your CouchDB views using ClojureScript.
Write your views/filters/validators in Clojure(Script), run the results in CouchDB or Cloudant — no special view servers, no special configuration, no JavaScript!
Super-experimental, but works.
clutch-clojurescript is available in clojars. Add it to your Maven project's pom.xml
:
<dependency>
<groupId>com.cemerick.clutch</groupId>
<artifactId>clutch-clojurescript</artifactId>
<version>0.0.1</version>
</dependency>
or your leiningen/cake project.clj
:
[com.cemerick.clutch/clutch-clojurescript "0.0.1"]
This is an extension of Clutch, the CouchDB client library and view server for Clojure.
- Load Clutch as you usually would.
- Make sure you've loaded clutch-clojurescript, e.g.
(require 'com.cemerick.clutch.cljs-views)
, or(:require com.cemerick.clutch.cljs-views)
in yourns
form. Note that you'll never need to directly access anything defined incom.cemerick.clutch.cljs-views
— you only need to load the namespace to allow it to register a multimethod implementation in clutch's core API. - Save a view using Clutch's usual
save-view
function:
(with-db "your_database"
(save-view "design_document_name"
(view-server-fns :cljs
{:your-view-name {:map (fn [doc]
(js/emit (aget doc "_id") nil))}})))
That's an example of a silly view, but should demonstrate the general pattern. Note the js/emit
function; after ClojureScript compilation, this results in a call to the emit
function defined by the standard CouchDB Javascript view server for emitting an entry into the view result. Follow the same conventions for reduce functions, filter functions, validator functions, etc.
Your views can utilize larger codebases; just include your "top-level" ClojureScript forms in a vector:
(with-db "your_database"
(save-view "design_document_name"
(view-server-fns {:language :cljs
:main 'couchview/main}
{:your-view-name {:map [(ns couchview)
(defn concat
[id rev]
(str id rev))
(defn ^:export main
[doc]
(js/emit (concat (aget doc "_id") (aget doc "_rev")) nil))]}})))
The ns
form here can require other ClojureScript files on your classpath, refer to macros, etc. When using this longer form, remember to do three things:
- You must provide a map of options to
view-server-fns
;:cljs
becomes the:language
value here. - Specify the "entry point" for the view function via the
:main
slot,'couchview/main
here. This must correspond to an exported, defined function loaded by some ClojureScript, either in your vector literal of in-line ClojureScript, or in some ClojureScript loaded via a:require
. - Ensure that your "entry point" function is exported; here,
main
is our entry point, exported via the^:export
metadata.
These last two points are required because of the default ClojureScript compilation option of :advanced
optimizations.
The view-server-fns
macro provided by Clutch (version 0.3.0-SNAPSHOT
and later) takes as its first argument some options to pass along to the view transformer specified in that options map's :language
slot. The clutch-clojurescript view transformer passes this options map along to the ClojureScript/Google Closure compiler, with defaults of:
{:optimizations :advanced
:pretty-print false}
So you can e.g. disable :advanced
optimizations and turn on pretty-printing by passing this options map to view-server-fns
:
{:optimizations :simple
:pretty-print true
:language :cljs}
If you really want to see what Javascript ClojureScript is generating for your view function(s), call com.cemerick.clutch.cljs-views/view
with an options map as described above (nil
to accept the defaults) and either an anonymous function body or vector of ClojureScript top-level forms.
- ClojureScript / Google Closure produces a very large code footprint, even for the simplest of view functions. This is apparently an item of active development in ClojureScript.
- In any case, the code size of a view function string should have little to no impact on runtime performance of that view. The only penalty to be paid should be in view server initialization, which should be relatively infrequent. Further, the vast majority of view runtime is dominated by IO and actual document processing, not the loading of a handful of JavaScript functions.
Ping cemerick
on freenode irc or twitter if you have questions or would like to contribute patches.
Copyright © 2011-2012 Chas Emerick and other contributors.
Licensed under the EPL. (See the file epl-v10.html.)