clj-metasearch
Happy to say that a little utility library of mine, clj-metasearch was released earlier this week.
This library allows you to search through all Clojure namespaces in the current classpath for vars which have metadata matching a predicate. This has a number of potential uses, such as automatically finding functions, or other types of vars that have metadata marking them as some kind of "plugin" for the application. You could do something like:
Which would scan the currently loaded namespaces only for any vars containing metadata with a :myapp-plugin
key
which had a "truthy" value. find-vars
returns a sequence of maps:
You can use var-get
on the :var
value to get the actual value found. I'll likely be changing this return value
format somewhat and possibly introducing a kind of "transform" function as an additional optional argument to
find-vars
that can be used to transform these results as they are found so the return value is exactly in the format
you need.
If you wanted to scan all namespaces, including ones that have yet to be loaded:
The extra parameter will cause each namespace to be loaded via require
before it is checked. This can potentially
cause problems or warnings to be output. For example, if namespaces are loaded that redefine vars, or other namespaces
that can't be loaded in the current JVM version (clojure.core.reducers
is an example of this, it can't be loaded on
Java 6 without some extra library also being present).
When using the :require-all-namespaces?
parameter it's usually best to supply an extra predicate to limit the number
of Clojure namespaces that are checked (if this is at all possible for your use case):
Example: Automatic Compojure Route Discovery
So, I originally put this library together because I wanted to be able to automatically find Compojure routes and have them get added to the Ring handler routes vector without me needing to explicitly list them all out. This is admittedly quite a minor thing to need to do, but it has always seemed silly to me that adding routes to a Ring handler is a manual process in your typical Clojure web app.
Right now I just use a couple macros and a single function for this automatic Compojure route discovery:
The register-routes
and register-restricted-routes
macros are drop-in replacements for Compojure's defroutes
and
lib-noir's def-restricted-routes
. Example use of find-routes
:
Would find all the Compojure routes defined with the register-routes
and/or register-restricted-routes
macros and
also append the routes in app-routes
to this list. You would then pass the returned list off to your Ring handler.