Project

dami

0.0
The project is in a healthy, maintained state
Dami is a modern, minimal ORM focusing on a clean query DSL, explicit data validation, and secure attribute protection.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

Runtime

>= 2.4, < 4
~> 2.0
~> 1.2
 Project Readme

Dami

A lightweight, policy-oriented ORM for Ruby on SQLite. One gem, no framework required.

  • Four-pillar DSL — structure (Dami.model), write rules (Dami.behavior), queries (Dami.scopes), presentation (Dami.present). Put something in the wrong block and Dami tells you where it goes.
  • Hardened writes by default — unknown fields raise, protected fields need an explicit permit:, every value is bound (never interpolated).
  • Real constraints — null:, unique:, default:, references: in migrations; foreign keys are enforced; violations come back as Dami::NotNullViolation, Dami::UniqueConstraintViolation, Dami::ForeignKeyViolation.
  • Flows — multi-step business operations that run in one transaction, roll back on failure, and fire side effects only after the commit.
  • Small and fast — a connection pool, WAL, prepared-statement cache, and nothing you didn't ask for.

Install

# Gemfile
gem "dami"

Five-minute tour

require "dami"

Dami.connect(:default, adapter: :sqlite, path: "app.db")

# Schema (or write a migration — see docs/09.Migrations.md)
Dami::Migration.new(Dami.database).create_table(:users) do |t|
  t.field :id, :primary_key
  t.field :email, :string, null: false, unique: true
  t.field :name, :string, null: false
  t.field :role, :string, default: "member"
  t.timestamps
end

# Structure
Dami.model :users do
  fields do
    field :email, :string
    field :name, :string
    field :role, :string
    field :created_at, :datetime
    field :updated_at, :datetime
  end
end

# Write-side rules
Dami.behavior :users do
  validate do
    rule :email, :required, :email
    rule :name, :required
  end
  protection { protect :role }
end

# Collection queries
Dami.scopes :users do
  scope :admins, -> { where(role: "admin") }
end

user = Dami.db(:users).create(email: "ana@example.com", name: "Ana")
user[:id]          # => 1
user.name          # => "Ana"
user[:created_at]  # => "2026-09-12 18:40:00" (UTC)

Dami.db(:users).where(id: user[:id]).update(name: "Ana G.")
Dami.db(:users).admins.count                 # => 0
Dami.db(:users).where(role: "admin").to_a    # => []

Dami.db(:users).create(email: "not-an-email", name: "")
# => Dami::ValidationError, errors: { email: ["must be valid email"], name: ["is required"] }

Dami.db(:users).where(id: 1).update(role: "admin")
# => Dami::ProtectionError (protected field) — pass permit: [:role] where you mean it

Documentation

Everything is in docs/, in reading order:

  1. Getting Started
  2. Models and Fields
  3. Querying
  4. Creating, Updating, Deleting
  5. Validation
  6. Protection
  7. Associations
  8. Scopes
  9. Migrations
  10. Flows and Commands
  11. Localization
  12. The Dami Way

Scope

SQLite only, on purpose. If you need PostgreSQL or MySQL today, Dami is not the right tool yet.

Development

bundle install
rake test        # ruby test/run_all.rb
rake build       # gem build dami.gemspec

License

MIT — see LICENSE.