A fully featured, data-driven database library for Clojure.
It is said that Gungnir could strike any target, regardless of the wielder's skill.
- Developer, speaking to the database admin.
Dutch Clojure Meetup - Gungnir
(gungnir.database/make-datasource!
{:adapter "postgresql"
:username "postgres"
:password "postgres"
:database-name "postgres"
:server-name "localhost"
:port-number 5432})
(def account-model
[:map
[:account/id {:primary-key true} uuid?]
[:account/email {:before-save [:string/lower-case]
:before-read [:string/lower-case]}
[:re {:error/message "Invalid email"} #".+@.+\..+"]]
[:account/password {:before-save [:bcrypt]} [:string {:min 6}]]
[:account/password-confirmation {:virtual true} [:string {:min 6}]]
[:account/created-at {:auto true} inst?]
[:account/updated-at {:auto true} inst?]])
(gungnir.model/register!
{:account account-model})
(defn password-match? [m]
(= (:account/password m)
(:account/password-confirmation m)))
(defmethod gungnir.model/validator :account/password-match? [_]
{:validator/key :account/password-confirmation
:validator/fn password-match?
:validator/message "Passwords don't match"})
(defmethod gungnir.model/before-save :bcrypt [_k v]
(buddy.hashers/derive v))
(defn attempt-register-account [request]
(-> (:form-params request)
(gungnir.changeset/cast :account)
(gungnir.changeset/create [:account/password-match?])
(gungnir.query/save!)))
(gungnir.query/find-by! :account/email "[email protected]") ;; => {:account/email "[email protected]",,,}
(-> (gungnir.query/limit 5)
(gungnir.query/select :account/id :account/email)
(gungnir.query/all! :account)) ;; => [{:account/email "..." :account/id "..."},,,]
Gungnir is still in its design phase and can result in breaking changes while on the SNAPSHOT version. Any breaking changes will be reflected in the updated documentation.
Add the following dependencies to your project.clj
:dependencies [[kwrooijen/gungnir "0.0.2-xxxxxxxx.yyyyyy-z"]
;; Optionally for frontend validation
[kwrooijen/gungnir.ui "0.0.2-xxxxxxxx.yyyyyy-z"]
,,,]
The Clojure community tends to lean towards the "pick the libraries that you need" method rather than using a "framework" when building an application. This can make it challenging for new users. Once you're familiar with the Clojure ecosystem you'll know which libraries you prefer and create your own setup. And that's exactly what I've done.
If you want complete control over your database stack, then this is probably not for you. If you're a beginner and are overwhelmed with all the necessary libraries and configuration, or if you're looking for a Clojure database library that aims to provide a quality of life experience similar to Ruby's ActiveRecord or Elixir's Ecto, then stick around.
I cannot stress this enough, I really dislike macros. Clojure and a large part of it's community have taught me the beauty of writing data driven code. With great libraries such as HoneySQL, Hiccup, Integrant, Reitit, Malli, I think this is the Golden age of Data Driven Clojure. I never want to see macros in my API again.
Include Gungnir in your project, and off you go! Gungnir includes everything for your database needs.
Gungnir uses models to provide data validation and seamless translation between Clojure and SQL. Read more
Inspired by Elixir Ecto's Changesets. Validate your data before inserting or updating it in your database. View the actual changes being made, and aggregate any error messages. Read more
Gungnir isn't here to reinvent the wheel. Even though we have an interface for querying the database, we can still make use of HoneySQL syntax. This allows us to expand our queries, or write more complex ones for the edge cases. Read more
Define your migrations using Clojure data structures and extend them as needed. You can also fallback to raw SQL if necessary. Read more
Relations are easily accessed with Gungnir. Records with relations will have
access to relational atoms
which can be dereffed to query any related
rows. Read
more,
and more
Gungnir also provides an extra package, gungnir.ui. Which provides some validation in the frontend. Read more
Read the guide for a full overview of all the features and how to use them.
The Gungnir code playground is a repository with an "interactive tutorial". Clone the repository and execute the code in the core namespace step by step.
In order to run the tests you'll need docker-compose. Make sure this is an up to date version. Inside of the root directory you can setup the testing databases with the following command.
docker-compose up -d
Then run the tests with lein
lein test
Released under the MIT License by Kevin William van Rooijen.