I want to experiment writing a web app with Clojure and CouchDB, but I can't find many examples to help me get started. Searching around the web a bit I see that I could use this combination of libraries:
https://leiningen.org/
http://www.luminusweb.net/
https://github.com/clojure-clutch/clutch
The first two seem popular, but what about clutch, it doesn't look actively developed -- is it a good choice?
Assuming I use clutch, I'm struggling to find much example code, this seems to work, but is it the right approach?
Project creation:
lein new luminus couchdb-test
Add this in project.clj in :dependencies:
[com.ashafa/clutch "0.4.0"]
Run project:
lein run
And then in the REPL:
(require ['com.ashafa.clutch :as 'clutch])
;; Test connection to DB - I've created one called wiki
(clutch/get-database "wiki")
;; Get a list of all documents
(clutch/with-db "wiki"
(clutch/all-documents))
;; Output all docs with contents
(clutch/with-db "wiki"
(clutch/all-documents {:include_docs true}))
;; Output titles of all docs that have one
(map (fn [result] (:title (:doc result)))
(clutch/with-db "wiki"
(clutch/all-documents {:include_docs true})))
Any corrections, hints, or pointers to better examples would be great.
Related
I have a terminal app built in Clojure and connected to MySQL, but I would like to know the simplest way to add a front-end to it. I came across this post (that is 5 years old) that recommends ring, and set it up: Add webapp frontend to existing clojure app.
After adding deps to project, added handler function to core.clj:
(defn handler [request]
{:status 200
:headers {"Content-Type" "text/html"}
:body "Hello World"})
Started a webserver and got output "Hello World."
Ok, now what? I am familiar with templates like Figwheel that allow you to build Clojurescript right out of the box (that doesn't come with a back-end?) and tools like Reagent that allow you to write React with Clojurescript, but what I am interested in is, how to add a front-end to an already existing terminal app, in whatever framework I choose, be it plain React, Clojurescript with Reagent, Angular, or even old-fashioned HTML/CSS/Javascript. It seems there are lots of templates but no instructions for how to do it from scratch.
Any of the following would have been acceptable answers: Selmer, Hiccup, Enlive.
Note: I'm a moderately experienced programmer in general and using clojure but have never done serious web development.
I set up a basic ClojureScript project using Chestnut and walked through the "Hello World" steps just fine. However I would really like to talk to my backend as well. For this purpose I redefined the Reagent code to be
(defn greeting []
[:input {:type "button"
:value (:text #app-state)
:on-click #(http/get {})}])
Which gets a 404 response when clicked. So at least I'm talking to somebody. I can also see evidence of my get-requests in the server.log file. However at this point I'm struggling with a number of conceptual points.
First of all http/get is a function defined in clj-http.client, which wasn't part of the Chestnut setup. It feels like I'm already off track if I have to go hunting for libraries to send something as basic as a get-request.
Secondly the file for the user namespace has the following lines predefined by Chestnut:
(def http-handler
(wrap-reload #'mypage.server/http-handler))
(defn run []
(figwheel/start-figwheel!))
I can't see any place where the http-handler is ever used. So I don't understand what that definition even does.
Also the way I understand Figwheel, when I call "run" it'll spin up a new web server which then a) serves the index.html and b) connects to my browser via some TCP port and starts pumping new JavaScript through that connection. This second part is very speculative on my part. If this is actually what happens my next question would be if Figwheel also needs to sit on the other side of that connection or if browsers have some common API that allows code reloading from the outside.
Lastly I can kinda tell that the ring routes and http-handler defined in the mypage/server.clj file (below) are being called somehow, since modifying these changes the error from the get-request, however it's a complete mystery to me how this works. The way I understand it the get-request I'm sending from the browser is sent to the Figwheel-server, the origin of the site. I have no reason to believe that Figwheel knows anything about the http-handlers I've defined in the server file.
(defroutes routes
(GET "/" _
{:status 200
:headers {"Content-Type" "text/html; charset=utf-8"}
:body (io/input-stream (io/resource "public/index.html"))})
(resources "/"))
(def http-handler
(-> routes
(wrap-defaults api-defaults)
wrap-with-logger
wrap-gzip))
For a ClojureScript project (i.e. not Clojure), I believe you want this: https://github.com/r0man/cljs-http
I don't have a complete answer, but I do have a couple points that might help.
Clojurescript ultimately compiles down to JavaScript, and makes heavy use of (and has access to) the Google Closure library. So if you really want to, you can use JavaScript interop to just make an AJAX call from the client-side, just like you would in JS. The closure library provides a wrapper for this---see docs here https://developers.google.com/closure/library/docs/xhrio . But there are also several easy http and Ajax libraries for clojurescript, so why not use them? Another part of the joy and magic of clojurescript is that the Google closure optimizations that get applied do lovely things like strip out dead code, so I believe (and someone else can correct me if I'm wrong) that there is little (no?) production cost to putting some extra libraries in.
Figwheel is ultimately dev, not production, and doesn't depend on the http server that you set up for production use. Indeed, there are templates out there for front-end-only cljs projects that still use figwheel--- here's one example. Figwheel spins its own server to push changes to the browser, I'm not quite sure how it works.
Beginner here.
Can I compile an existing Clojure script to run it on the web using ClojureScript?
Let's say that I have a script that prints Hello world in my terminal, and I want to print that text on the browser. Should I rewrite a whole script with ClojureScript syntax, or should I just compile it using another compiler?
(ns clojure-hello-world.core
(:gen-class))
(defn -main [& args]
(println "Hello World"))
(Long answer :P)
Even though Clojure and ClojureScript share a good amount of features, there are some that are specific to one or the other. For example there are no real classes in JavaScript so the :gen-class specification in the ns form doesn't make much sense.
One important fact is that the syntax of both Clojure and ClojureScript is exactly the same, differences have to do mostly with the host VM in which they run (Java VM in the case of Clojure and JavaScript VM in the case of ClojureScript).
There is a list of the differences between the two Clojure implementations here.
There's also a tool called cljx to "write a portable codebase targeting Clojure/ClojureScript". Recently there has been some discussion on the Clojure Dev group around finally implementing feature expressions which would on one hand deprecate the use of cljx but on the other complicate the work that tools have to do to extract information from Clojure source files.
I would start with lein-cljsbuild to get started. This will get you going with a nice edit eval and look at browser loop. It's well worth getting this setup first because it makes learning ClojureScript much more fun. I promise it's worth the hassle. If you need more interactive support the folks in #clojure on freenode are very kind and helpful.
Basically, the Browser executes JavaScript. You compile your ClojureScript code to JavaScript. The Browser loads your JavaScript via an HTML page. So, you have to create an HTML Page and point your Browser at it.
The simplest way I got started was to use Luminous (http://www.luminusweb.net/docs/clojurescript.md).
However, Chestnut (https://github.com/plexus/chestnut) looks promising.
I have been following clojure for some time, and some of its features are very exciting (persistent data structures, functional approach, immutable state). However, since I am still learning, I would like to understand how to apply in real scenarios, prove its benefits and then evolve and apply for more complex problems. i.e. what are the easy wins with clojure (e.g. in an e-commerce setup) that can be used to learn as well as ascertain its benefits.
I have investigated clojure based web frameworks, but I am not keen on them, as they need hand-written javascript (as against gwt). So for me, it is more about backend processing. Can someone explain where they applied clojure (in real deployments), and how did it prove useful (and the cons, if any, of using clojure)
Further analysis:
Lazy evaluation is an oft example of power of Lisp. Clojure being a Lisp, offers the same advantage. So, a real world example of such an application (in context of clojure) would help me gain insight.
You have mentioned that you work with CSV files. I found these to be very helpful, because I had to parse a csv file -- used clojure-csv; then extract certain columns from that csv file using sequence functions; interleave http form field names using zipmap; and then make http calls to an ASP application using clj-http.client.
(def accumail-url-keys ["CA", "STREET", "STREET2", "CITY", "STATE", "ZIP", "YR", "BILL_NO", "BILL_TYPE"] )
.
.
.
(defn ret-params
"Generates all q-parameters and returns them in a vector of vectors."
[all-csv-rows]
(reduce
(fn [param-vec one-full-csv-row]
(let [q-param (zipmap accumail-url-keys one-full-csv-row)
accu-q-param (first (rest (split-at 3 q-param)))
billing-param (first (split-at 3 q-param))]
(conj param-vec [accu-q-param billing-param])))
[]
all-csv-rows))
That project was an accelerated Clojure learning exercise.
Two sites 4Clojure.com and http://www.cis.upenn.edu/~matuszek/cis554-2010/Assignments/clojure-01-exercises.html are good places to start working on Clojure exercises. You can build on those.
Also the Clojure Google Group is a very helpful place to get information.
The Univ of Penn CIS exercises, as simple as they might seem, have given me a lot to digest, especially getting the skeleton of a tree, and recently the skeleton problem got a long discussion in the Google Clojure group.
Good luck.
cmn
I am trying the various Getting started examples and I can get a basic hello world example working with basic HTML in the route as such
(ns hello-world
(:use compojure.core ring.adapter.jetty)
(:require [compojure.route :as route]))
(defroutes example
(GET "/" [] "<h1>Hello World Wide Web!</h1>"))
(run-jetty example {:port 8080})
But when I attempt to use the html helpers like so
(ns hello-world
(:use compojure ring.adapter.jetty)
(:require [compojure.route :as route]))
(defroutes example
(GET "/" []
(html [:h1 "Hello World"])))
(run-jetty example {:port 8080})
Then I get the following error
[null] Exception in thread "main" java.io.FileNotFoundException: Could not locate compojure__init.class or compojure.clj on classpath: (core.clj:1)
As W55tKQbuRu28Q4xv mentions in a comment, you use (:use compojure ...) in the second example. You should switch to (:use compojure.core ...) and then maybe pull in some additional dependencies for the other functionality that you use (like hiccup (<- this is a link to the GitHub repo), which is now a separate project, for the HTML-building DSL).
My guess is that you're trying to follow some tutorials written for Compojure 0.3 while using Compojure 0.4. The latter does not include the compojure namespace at all and has been slimmed down a lot, with the basic HTTP handling delegated to ring and various other pieces of functionality spun off to separate projects (like the aforementioned hiccup).
Fortunately there are good resources on the 0.3 -> 0.4 transition, e.g. this blog entry by Brenton Ashworth. If you can't find something that's been removed from Compojure proper, chances are you'll be able to learn where to find it now from that. See also this follow-up discussion on Compojure's Google group for errata and additional details.
I played around with a Compojure "Hello World" and had this problem (as well as many others that are getting muddled in my brain). Another complication is a lot of the Compojure documentation on the web is already out of date. Bottom line, these are the step you want to follow:
Have an up-to-date version of Leiningen. Make sure you follow the installation instructions on the github site. (Do not go through macports; their Leiningen is out of date.)
Follow Compojure instructions here.
Note that the file name is incorrect. It should be src/hello_www/core.clj NOT src/hello-www/core.clj.