• Stars
    star
    160
  • Rank 234,703 (Top 5 %)
  • Language
    Clojure
  • License
    MIT License
  • Created over 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A fully featured, data-driven database library for Clojure.

Gungnir

A fully featured, data-driven database library for Clojure.

Build Status codecov Dependencies Status Clojars Project Slack

It is said that Gungnir could strike any target, regardless of the wielder's skill.

- Developer, speaking to the database admin.

Read the guide

Gungnir code playground

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 "..."},,,]

Installation

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

Versions

:dependencies [[kwrooijen/gungnir "0.0.2-xxxxxxxx.yyyyyy-z"]
               ;; Optionally for frontend validation
               [kwrooijen/gungnir.ui "0.0.2-xxxxxxxx.yyyyyy-z"]
               ,,,]

Rationale

Plug & Play setup with quality of life

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.

Data Driven

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.

Features

Plug & Playâ„¢

Include Gungnir in your project, and off you go! Gungnir includes everything for your database needs.

Models

Gungnir uses models to provide data validation and seamless translation between Clojure and SQL. Read more

Changesets

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

Querying & Extension to HoneySQL

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

Migrations

Define your migrations using Clojure data structures and extend them as needed. You can also fallback to raw SQL if necessary. Read more

Relational mapping

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

Frontend validation

Gungnir also provides an extra package, gungnir.ui. Which provides some validation in the frontend. Read more

Resources

Guide

Read the guide for a full overview of all the features and how to use them.

Code Playground

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.

Developing

Testing

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

Author / License

Released under the MIT License by Kevin William van Rooijen.

More Repositories

1

cargo.el

Emacs Minor Mode for Cargo, Rust's Package Manager.
Emacs Lisp
167
star
2

exrm_docker

DEPRECATED: Exrm plugin to dockerize your Elixir release
Elixir
50
star
3

hiccup-cli

Command line tool / Emacs plugin to convert HTML to Hiccup syntax.
Emacs Lisp
43
star
4

tauri-cljs

DEPRECATED: Leiningen template for Tauri and Clojurescript
Clojure
31
star
5

transpose-mark

Emacs libary for transposing data using the mark
Emacs Lisp
17
star
6

gram

A server-side rendering framework based on Hotwire
Clojure
9
star
7

clj-turbo

Clojure wrapper for Turbo
Clojure
9
star
8

clj-stimulus

Clojure wrapper for Stimulus
Clojure
8
star
9

.emacs.d

My Emacs configurations
Emacs Lisp
6
star
10

spec-signature

Write spec signatures for functions
Clojure
5
star
11

indy

A customizable indentation minor mode for Emacs
Emacs Lisp
5
star
12

snaplet-coffee

A Haskell Snaplet based off of snaplet-fay, but for coffeescript
Haskell
5
star
13

LazyCasts

A collection of LazyCasts code used in episodes.
Haskell
4
star
14

integrant-tools

A library with helper functions, reader tags, and init-keys for Integrant
Clojure
3
star
15

duct-gungnir

Duct library for Gungnir
Clojure
3
star
16

feit

WIP Clojure game engine
Clojure
2
star
17

.spacemacs.d

Emacs Lisp
2
star
18

gungnir.ui

UI helpers for the Gungnir library
Clojure
2
star
19

duct-middleware-anti-forgery

Duct middleware for anti forgery (CSRF)
Clojure
2
star
20

ArcadiaGodotNetwork

Multiplayer network management in ArcadiaGodot
Clojure
2
star
21

gungnir-playground

Example code for the Gungnir library.
Clojure
2
star
22

murk

Murk is an Elixir data type validation library.
Elixir
2
star
23

haskell-coffee

Haskell library that provides functions for using the coffeescript compiler
Haskell
1
star
24

cljs-auto

A tool to automatically convert EDN files to Clojurescript, and automatically require namespaces
Clojure
1
star
25

.doom.d

Emacs Lisp
1
star
26

duct-drawbridge

Duct handler / middleware for Drawbridge
Clojure
1
star
27

keydox

Keyword metadata through EDN files
1
star
28

advent-of-code

Clojure
1
star
29

krita-fill-discontiguous

Python
1
star
30

lumber

Phoenix Channel interface builder, input / output type checker, and Elm Channel code generator.
Elixir
1
star
31

lita-global-command

Global Command Extension for your Lita Robot routes.
Ruby
1
star