norm

Nim ORM.

Readme

Norm: A Nim ORM

Build Status Nimble

Norm is an object-oriented, framework-agnostic ORM for Nim that supports SQLite and PostgreSQL.

Norm works best with Norman.

Quickstart

Install Norm with Nimble:

$ nimble install norm

Add Norm to your .nimble file:

requires "norm"

Here's a brief intro to Norm. Save as hellonorm.nim and run with nim c -r hellonorm.nim:

import norm/sqlite                        # Import SQLite backend; ``norm/postgres`` for PostgreSQL.

import unicode, options                   # Norm supports `Option` type out of the box.

import logging                            # Import logging to inspect the generated SQL statements.
addHandler newConsoleLogger()


db("petshop.db", "", "", ""):             # Set DB connection credentials.
  type                                    # Describe models in a type section.
    User = object                         # Model is a Nim object.
      age: Positive                       # Nim types are automatically converted into SQL types
                                          # and back.
                                          # You can specify how types are converted using
                                          # ``parser``, ``formatter``,
                                          # ``parseIt``, and ``formatIt`` pragmas.
      name {.
        formatIt: ?capitalize(it)         # E.g., enforce ``name`` stored in DB capitalized.
      .}: string
      ssn: Option[int]                    # ``Option`` fields are allowed to be NULL.


withDb:                                   # Start DB session.
  createTables(force=true)                # Create tables for objects.
                                          # ``force=true`` means “drop tables if they exist.”

  var bob = User(                         # Create a ``User`` instance as you normally would.
    age: 23,                              # You can use ``initUser`` if you want.
    name: "bob",                          # Note that the instance is mutable. This is necessary,
    ssn: some 456                         # because implicit ``id``attr is updated on insertion.
  )
  bob.insert()                            # Insert ``bob`` into DB.
  echo "Bob ID = ", bob.id                # ``id`` attr is added by Norm and updated on insertion.

  discard insertId User(                  # Insert an immutable model instance and return its ID.
    age: 12,
    name: "alice",
    ssn: none int
  )

withCustomDb("mirror.db", "", "", ""):    # Override default DB credentials
  createTables(force=true)                # to connect to a different DB with the same models.

withDb:
  let bobs = User.getMany(                # Read records from DB:
    100,                                  # - only the first 100 records
    cond="name LIKE 'Bob%' ORDER BY age"  # - matching condition
  )

  echo "Bobs = ", bobs

withDb:
  var bob = User.getOne(1)                # Fetch record from DB and store it as ``User`` instance.
  bob.age += 10                           # Change attr value.
  bob.update()                            # Update the record in DB.

  bob.delete()                            # Delete the record.
  echo "Bob ID = ", bob.id                # ``id`` is 0 for objects not stored in DB.

withDb:
  transaction:                            # Put multiple statements under ``transaction`` to run
    for i in 1..10:                       # them as a single DB transaction. If any operation fails,
      var user = User(                    # the entire transaction is cancelled.
        age: 20+i,
        name: "User " & $i,
        ssn: some i
      )
      insert user

withDb:
  dropTables()                            # Drop all tables.

Reference Guide

Model Declaration

Connection

Setup

Teardown

Create Records

Read Records

Update Records

Delete Records

Transactions

Migrations

To apply and undo migrations in your projects, use Norman.

Contributing

Any contributions are welcome: pull requests, code reviews, documentation improvements, bug reports, and feature requests.

  • See the [issues on GitHub](http://github.com/moigagoo/norm/issues).

  • Run the tests before and after you change the code.

    The recommended way to run the tests is via [Docker](https://www.docker.com/) and [Docker Compose](https://docs.docker.com/compose/):

    $ docker-compose run --rm tests                     # run all test suites
    $ docker-compose run --rm test tests/tpostgres.nim  # run a single test suite
    

    If you don't mind running two PostgreSQL servers on postgres_1 and postgres_2, feel free to run the test suites natively:

    $ nimble test
    

    Note that you only need the PostgreSQL servers to run the PostgreSQL backend tests, so:

    $ nim c -r tests/tsqlite.nim    # doesn't require PostgreSQL servers, but requires SQLite
    $ nim c -r tests/tobjutils.nim  # doesn't require anything at all
    
  • Use camelCase instead of snake_case.

  • New procs must have a documentation comment. If you modify an existing proc, update the comment.

  • Apart from the code that implements a feature or fixes a bug, PRs are required to ship necessary tests and a changelog updates.

❤ Contributors ❤

Norm would not be where it is today without the efforts of these fine folks: https://github.com/moigagoo/norm/graphs/contributors

Need help? Read Nimble
Author:
moigagoo
Available versions:
License: MIT

Project website Hosted docs