-
Notifications
You must be signed in to change notification settings - Fork 0
Post Processing
There are many situations where we want to apply some transformation to data that cuts across many different parts of the data model or application model. For example, we may want to format some output as currency or convert some input from a string to a number.
In our current application we would like to round a number to two decimal places. We will do this with a post processor just to show how they work.
Since we will be writing ClojureScript code to do this formatting we
do not want to include it in the behavior namespace. Instead, we
will create a new namespace for post processing code named
tutorial-client.post-processing and we will add the post processor
to our dataflow definition just before we create the application in
the tutorial-client.start namespace.
Create the file app/src/tutorial_client/post_processing.cljs.
(ns tutorial-client.post-processing)Create a function which will round a number to the desired number of decimal places.
(defn- round [n places]
(let [p (Math.pow 10 places)]
(/ (Math.round (* p n)) p)))Next we create the post processing function. A post processing function takes a message and returns a sequence of messages. Post processing functions can filter, transform and expand messages.
(defn- round-number-post [[op path n]]
[[op path (round n 2)]])Next we create a function which will add a :post key to the dataflow
definition.
(defn add-post-processors [dataflow]
(-> dataflow
(update-in [:post :app-model] (fnil conj [])
[:value [:main :average-count] round-number-post])))Finally, in tutorial-client.start, we require
tutorial-client.post-processing
[tutorial-client.post-processing :as post]and then update the call to app/build so that it will add the
post processor to the dataflow definition.
app (app/build (add-post-processors behavior/example-app))The final version of the create-app function looks like this.
(defn create-app [render-config]
(let [app (app/build (post/add-post-processors behavior/example-app))
render-fn (push-render/renderer "content" render-config render/log-fn)
app-model (render/consume-app-model app render-fn)]
(app/begin app)
(p/put-message (:input app) {msg/type :inc msg/topic [:my-counter]})
{:app app :app-model app-model}))In the browser we should now see a rounded value for :average-count.
The application's behavior is now complete. Notice that we have written all of our behavior code as Clojure code. If we were writing tests first, or as we go, we could have arrived at this point without ever opening a browser. Had we done that, we could now open a browser and see everything work in the Data UI.
It is also important to point out what we have not done. We have got the core behavior of our application working without thinking about rendering or the complexities of the browser or working on our service. This has allowed us to focus all of our attention on what we actually cared about at this stage of development. Begin able to focus in this way is very helpful when our applications become more complex.
In the next few sections we will focus on rendering.
The tag for this step is v0.0.7.