Skip to content
Ryan Neufeld edited this page Jul 9, 2013 · 9 revisions

To follow along with this section, start with tag v2.0.7.

There are many situations where you want to apply some transformation to data that cuts across many different parts of the data model or application model. For example, you may want to format some output as currency or convert some input from a string to a number.

In the current application, it would be nice to round the average counter value to two decimal places. This section will show how to do this with a post processor.

Creating the post processor

The post processor code will be ClojureScript code so it should not be included in the tutorial-client.behavior namespace. Create a new namespace named tutorial-client.post-processing.

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

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

Create a function which will add this post processor to any dataflow definition.

(defn add-post-processors [dataflow]
  (-> dataflow
      (update-in [:post :app-model] (fnil conj [])
                 [:value [:main :average-count] round-number-post])))

Post processors are handled in the same way as transform functions. In the example above, the configuration is

[:value [:main :average-count] round-number-post]

In the dataflow definition, this lives under [:post :app-model]. This means that any message placed on the app model queue which is a :value operation on the path [:main :average-count] will be passed to the round-number-post function and then be replaced with the result of that function call.

Adding the post processor to the dataflow definition

In the namespace tutorial-client.start, 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 (post/add-post-processors behavior/example-app))

The final version of the create-app function should now look 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 you should now see a rounded value for :average-count.

Next steps

The application's behavior is now complete. Notice that you have written all of the behavior code as Clojure code. If you were writing tests first, or as you go, you could have arrived at this point without ever opening a browser. Had you done that, you could now open a browser and see everything work in the Data UI.

It is also important to point out what you have not done. The core behavior of the application is now working and you have not had to think about rendering or the complexities of the browser or working on the service. pedestal-app has allowed us to focus all of our attention on what we actually cared about at this stage of development. Being able to focus in this way will become even more important as the applications that we build become more complex.

In the next few sections you will learn how to render this application. If you are not interested in templating, you may pretend that a designer has done that work for you and skip to the [[Slicing Templates]] section where you will learn how to make use of an existing template. If you skip ahead, checkout the tag v2.0.9 before continuing on.

The tag for this section is v2.0.8.

Home | Making an HTML Template | Slicing Templates

Clone this wiki locally