Skip to content

Tutorial how to start a project with clojure and clojurescript

Notifications You must be signed in to change notification settings

swerter/cljs-calc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cljs-calculator

This is a short version of the excellent tutorial modern-cljs

To get things running:

git clone https://github.com/swerter/cljs-calc.git
cd cljs-calc

To run the web server:

lein ring server

The main differences are that it is a shorter version and that it contains also a testing tutorial. It shows how to setup the testing environment.

Usage

If you simply want to see the final application running: lein repl

There is also a Consular file. If you have consular installed you can also simply run

consular start Termfile

and server, autotests in clojure and clojurescript, repl, and cljsrepl start up each in its own tab.

Introduction

As an example of how such a clojurescript application can be set up we use develop here a calculator that calculates the multiplication of two numbers. This is a simple example but has all the elements of a bigger application: there are input elements, there is an output, and the calculation can be tested.

Let's start with a ring server

First we need to setup the project

lein new cljs-calc
cd cljs-calc

Now let's start with clojure server, that simply serves a static html page. For that we need to add the ring plugin. The ring plugin is an API to the http level.

In addition we also add the compojure to the stack, which is a routing library for the ring server.

Finally the project.cljs file should look like this:

  (defproject cljs-calc "0.1.0-SNAPSHOT"
    :description "FIXME: write description"
    :url "http://example.com/FIXME"
    :license {:name "Eclipse Public License"
              :url "http://www.eclipse.org/legal/epl-v10.html"}
    :dependencies [[org.clojure/clojure "1.4.0"]
                   [compojure "1.1.5"]]
    :plugins [;; ring plugin
              [lein-ring "0.8.3"]]

              ;; ring tasks configuration
              :ring {:handler cljs-calc.core/handler}
    )

We also need to setup the routes in the core.clj. Update the file src/cljs_calc/core.clj and fill in the following:

(ns cljs-calc.core
  (:use compojure.core)
  (:require [compojure.handler :as handler]
            [compojure.route :as route]))

;; defroutes macro defines a function that chains individual route
;; functions together. The request map is passed to each function in
;; turn, until a non-nil response is returned.
(defroutes app-routes
  ; to serve document root address
  (GET "/" [] "<p>Hello from compojure</p>")
  ; to serve static pages saved in resources/public directory
  (route/resources "/")
  ; if page is not found
  (route/not-found "Page not found"))

;; site function creates a handler suitable for a standard website,
;; adding a bunch of standard ring middleware to app-route:
(def handler
  (handler/site app-routes))

When you now start the ring server with

lein run server

you will see a browser window opening and the text appearing "Hello from compojure". (If the browser window did not open you can manually enter the url: http://localhost:3000)

Add tests for the clojure code

In best practice you should start with the tests. But as we are still the setup phase I only add tests now. First we need to add the midje dependency. Midje is a testing framework for clojure. We also add the plugin lein-midje to simplify running our tests.

Our project.clj now looks like this:

(defproject cljs-calc "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [compojure "1.1.5"]
                 [midje "1.5.0"]]
  :plugins [;; ring plugin
            [lein-ring "0.8.3"]
            [lein-midje "3.0.1"]]

            ;; ring tasks configuration
            :ring {:handler cljs-calc.core/handler}
  )

Now that the testing setup is done, let's create a function that adds two numbers together. Very simple, I know, nothing of much use. But the purpose of this project is to show how to setup clojure and clojurescript, not how to build astronomical calculations.

Replace the automatically generated tests test/cljs_calc/core_test.clj with the following (take care with the namespace section: the namespace needs to have the same name as the file, but with the underscore replaced with a dash):

(ns cljs-calc.core-test
  (:use [midje.sweet])
  (:require [cljs-calc.core :as core]))


  (facts "Adder calculates the sum of two numbers"
       (fact "1+1 = 2"
             (core/adder 1 1) => 2)
       (fact "2+2 = 4"
             (core/adder 2 2) => 4)
       (fact "0+0 = 0"
             (core/adder 0 0) => 0))

Running the tests with lein midje should return an error like Exception in thread "main" java.lang.RuntimeException: No such var: core/adder... because we do yet have implemented the adder function. Add the adder function to src/cljs-calc/core.cljs:

(ns cljs-calc.core
  (:use compojure.core)
  (:require [compojure.handler :as handler]
            [compojure.route :as route]))

(defn adder [a b]
  (+ a b))

;; defroutes macro defines a function that chains individual route
;; functions together. The request map is passed to each function in
;; turn, until a non-nil response is returned.
(defroutes app-routes
  ; to serve document root address
  (GET "/" [] (str "<p>Calculating: 2 + 2 = " (adder 2 2) "</p>"))
  ; to serve static pages saved in resources/public directory
  (route/resources "/")
  ; if page is not found
  (route/not-found "Page not found"))
;; site function creates a handler suitable for a standard website,
;; adding a bunch of standard ring middleware to app-route:
(def handler
  (handler/site app-routes))

Run again lein midje and now you should see in green All claimed facts (3) have been confirmed..

If you are like me you prefer to have the testing done automatically whenever you change a source or test file. To do so open a new window in the terminal and run:

lein midje --lazytest

If you still have your ring server running and reload the page you should now see our beautiful calculation of 2 + 2 = 4. If not, start the ring server again with:

lein run server

Intermezzo: Use consular to manage all these terminals

In the meantime we already have at least two terminal instances open: one for the ring server and the other with the midje autotest. If you are like me you also have the repl open to try out things. That makes already three terminal instances. To always open all these instances whenever I continue working on the project is a pain. Lucky for us there is help: Consular. To install consular you run

gem install consular

Afterwards, you need to add the core for the terminal program you use. For instance, for the mac os x terminal

gem install consular-osx

In case you use iTerm run

gem install consular-iterm

Finally, you also need to load the terminal driver by running

consular init

which should generate a configure file loading the correct driver for your teminal. In case of difficulties check the homepage of Consular.

Now that we have consular installed, we need to write a Termfile to configure what to start. Generate a file Termfile.term with the following content:

curdir = Dir.pwd

tab "Ring server" do
    run "cd #{curdir}"
    run "lein ring server"
  end
  tab "clj autotest" do
    run "cd #{curdir}"
    run "lein midje --lazytest"
  end
  tab "Repl" do
    run "cd #{curdir}"
    run "lein repl"
  end
end

License

Copyright © 2013 Michael J. Bruderer

Distributed under the Eclipse Public License, the same as Clojure.

About

Tutorial how to start a project with clojure and clojurescript

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published