I'm working on a Liberator project in Clojure. I've defined a series of routes which return JSON data computed by logic in some other namespace. I would like to be able to change the namespace that implements the logic programmatically so I can do something like this:
JAVA_OPTS='-DgameLogicNamespace=foo.logic.mock' lein ring server-headless 8080
I am currently doing it like this:
(ns foo.routes
(:require [compojure.core :refer :all]
[liberator.core :as lib :refer [defresource request-method-in]]
[liberator.representation :refer [ring-response]]))
(require
(vec
(cons (symbol (System/getProperty "gameLogicNamespace" "foo.logic.real"))
'[:as logic])))
This works, but feels a bit clunky. Is there an idiomatic way to accomplish what I want?
One of my main motivations is actually for unit testing routes with mock data, so if there's a nice solution for providing the mock logic only in tests (and not as a JVM system property), suggestions are welcome.
One of my main motivations is actually for unit testing routes with mock data, so if there's a nice solution for providing the mock logic only in tests (and not as a JVM system property), suggestions are welcome.
If you haven't already, take a look at ring-mock for some nice utilities to generate mock requests to test your Ring handlers.
If you're interested in providing mock versions of functions that provide the implementation of your application logic during unit tests, consider using with-redefs; it's pretty much custom-made for this purpose.
(ns my-app.handlers-test
(:require [clojure.test]
[my-app.handlers :as h]
[my-app.logic :as l]
[ring.mock.request :as r]))
(deftest test-simple-handler
(with-redefs [l/my-complicated-logic #(update-in % [:a] inc)]
(is (= {:a 2}
(h/my-handler (r/request :post "/foo" {:a 1}))))))
Related
What is the difference between core & inope?
I have a very brief idea that core is like the main equivalent in Java. And inope is like an interface between java and clojure, although I dont understand the purpose of inope entirely.
I found this in a project and this is my understanding:
inope.clj is used for writing java clojure interoperable functions.
The namespace contents imply that it functions like core.clj here.
in this inope.clj file, they have imported dependencies and defined java-clojure interoperable functions in gen-class as such :
(ns prject-avon.inope
(:require [prject-avon.ioutil :as utl]
[aero.core :as aero-core :refer (read-config)]
[clojure.java.data :as clj-data]
[malli.core :as m]
[malli.util :as mu]
[malli.instrument :as mi]
[malli.error :as me]
[malli.json-schema :as json-schema]
(:gen-class
:methods [ ^{:static true} [validateData [Object String] Boolean]
]))
<Functions are defined here>
Those are just names, there's no significance to them. In particular, I've never heard of inope myself. The only way you can reliably judge is by the namespace's contents and their usage. It's also very possible that a single namespace contains all sorts of unrelated stuff.
I'm writing a small debugging library and I would like to let users choose how to display data structures. I was imagining that users could require it in this kind of way:
(ns some-user-namespace
(:require
[clojure.pprint]
[my.library :with-args {print-fn clojure.pprint/pprint}]))
Is something like this possible, and if not, how can I solve this problem?
It's not possible to do it this way. If you really to offer this kind of setup, you could provide a configuration function to be called by the user after the import:
(ns some-namespace
(:require [my.library]))
(my.library/print-with! clojure.pprint/pprint)
Ending function name with ! is an idiomatic way of indicating that it's causing some side effects.
In your library it could look like:
(ns my.library)
(def config (atom {:printer println}))
(defn print-with! [new-printer]
(swap! config assoc :printer new-printer))
(defn my-lib-print [foo]
((:printer #config) foo))
EDIT: For a solution that does not require global, mutable state you can use dynamic bindings.
Lib:
(ns my.library)
(def ^:dynamic *printer* println)
(defn my-lib-print [foo]
(*printer* foo))
Usage:
(binding [my.library/*printer* clojure.pprint/pprint]
(my.library/my-lib-print {:hello "World"}))
These are the only two ways for some kind of external, contextual configuration I can think of. The only alternative is pure higher order function:
(defn my-lib-print [printer foo]
(printer foo))
I have a namespace that exposes common data-related functions (get-images, insert-user). I then have two database backends that have those same functions and implement them differently. They implement the interface as it were. Each backend is contained within a namespace.
I can't seem to be able to find a good solution on how to accomplish this.
I tried dynamically loading the ns but no luck. Once you do (:require [abc :as x]), the x isn't a real value.
I tried using defprotocol and deftype but that's all kinds of weird because the functions in the deftype need to be imported, too and that messes everything up for me.
Is there some idiomatic solution to this?
I don't see why protocols are not sufficient?
In ns data.api:
(ns data.api)
(defprotocol DB
(get-images [this])
(insert-user [this]))
In ns data.impl1:
(ns data.impl1
(:require [data.api :refer :all]))
(defrecord Database1 [connection-params]
DB
(get-images [_] ...)
(insert-user [_] ...))
Same thing in ns data.impl2.
Then when you go to use a particular db, just create the correct record:
(ns data.user
(:require [data.api :refer :all])
[data.impl1 :refer (->Database1)])
(defn use-db []
(let [db1 (->Database1 {})]
(get-images db1)))
I'm trying out Clojure web development with Ring + Compojure + lib-noir, and I can't figure out how to test the session state.
I think you can just mimic the style used for the actual session tests in ring: https://github.com/ring-clojure/ring/blob/master/ring-core/test/ring/middleware/session/test/cookie.clj.
Just create a cookie-store, and then read/write to it, and assert the handlers respond accordingly. Given you are also using lib-noir, perhaps this example is more appropriate: https://github.com/noir-clojure/lib-noir/blob/master/test/noir/session_test.clj.
If you mean for unit tests, you can use binding, which will create new bindings for the vars.
You can check a good explanation that can be found here.
A sample unit tests with lib-noir
(ns your.test.core
(:use [clojure.test])
(:require [noir.session :as s]))
(binding [s/*noir-session* (atom {})]
; store new sessions
(s/put! "xxxx" {:value "1234"})
(s/put! "my_session" {:value "abcdefg"})
; run tests
(is (= {:value "1234"} (s/get "xxxx")))
(is (= {:value "abcdefg"} (s/get "my_session"))))
You can check the source code of noir.session here.
I've seen several different ways for :use in clojure--what's the idiomatic/preferred method?
#1
(ns namespace.core
(:use [[something.core]
[another.core]]))
or #2 EDIT: Use this with conjunction with :only.
(ns namespace.core
(:use [something.core]
[another.core]))
or #3
(ns namespace.core
(:use [something.core
another.core]))
or #4
(ns namespace.core
(:use (something.core
another.core)))
or #5 EDIT: This is idiomatic, but one should be using :use as in #2
(ns namespace.core
(:use something.core
another.core))
Choice #5 is idiomatic, unless you are passing additional options such as :only, :exclude, etc. Colin's blog post covers the options in great detail.
The API for dealing with namespaces is unnecessarily difficult to learn. However, it is certainly capable enough for a wide variety of uses, so the pressure for a rewrite has yet to reach the boiling point for anyone.
Actually none of them are idiomatic. You should always have an :only clause in your :uses. Your best bet is adding :only to #2. If you don't want to enumerate all the vars you're taking from another namespace, consider (:require [foo.bar :as bar]).
One point of note that we should mention is that the
(:use (clojure set xml)) statement is considered a promiscuous operation
and therefore discouraged. [...] When organizing your
code along namespaces, it’s good practice to export and import only those
elements needed.
-from the Joy of Clojure, page 183.
The one exception is that a test namespace should bare-use the namespace it tests.
The cases 1, 3 and 4 are not valid and throw some Exception. I haven't seen 2 - only in combination with :only or the like.
(ns namespace.core
(:use
[something.core :only (x)]
another.core))
I usually use 5.
In Clojure 1.4+ I wouldn't use use at all. require can do all that use can do now, so forget about use. One less thing to worry about.
If you want use-like behaviour (still bad form, imo) you can do:
(ns namespace.core
(:require
[something.core :refer :all]
[another.core :refer :all]))
If you want :use .. :only behaviour, use:
(ns namespace.core
(:require
[something.core :refer [foo bar]]
[another.core :refer [quux]]))
More detail: In Clojure 1.4 what is the use of refer within require?