A faithful port of Laravel's Eloquent ORM to Rust.
Rust has excellent query builders and entity-first ORMs, but nothing with Eloquent's ActiveRecord
ergonomics. Ferroquent brings that feel - User::query().where_("votes", ">", 100).get(db).await -
with models, relations, eager loading, existence queries, scopes, soft deletes, casts, observers,
factories, a schema builder, and migrations. It runs on MySQL, MariaDB, and PostgreSQL through
sqlx, behind a driver seam (copied from Laravel) so other backends can be added without touching
the core.
use ferroquent::prelude::*;
#[derive(Model, Clone, Debug, Default)]
#[ferroquent(soft_deletes)]
struct User {
id: u64,
#[ferroquent(fillable)] name: String,
#[ferroquent(fillable)] email: String,
#[ferroquent(fillable)] votes: i32,
created_at: Option<chrono::NaiveDateTime>,
updated_at: Option<chrono::NaiveDateTime>,
deleted_at: Option<chrono::NaiveDateTime>,
posts: HasMany<Post>,
state: ModelState<User>,
}
# async fn demo() -> ferroquent::core::error::Result<()> {
Ferroquent::boot(ConnectionConfig::from_url("mysql://root:secret@127.0.0.1/app")?)?;
let conn = Ferroquent::connection(None).await?;
let db = conn.as_ref();
// Create (mass-assigned), then a dirty-only UPDATE.
let mut user = User::create(db, record([
("name", Value::Str("Taylor".into())),
("email", Value::Str("taylor@example.com".into())),
("votes", Value::Int(10)),
])).await?;
user.votes = 11;
user.save(db).await?;
// Eloquent-style querying with eager loading (no N+1).
let mut q = User::query();
q.where_("votes", ">", 8).with(["posts"]).order_by_desc("votes");
let active = q.get(db).await?;
# Ok(()) }- Models -
#[derive(Model)]with casts, dirty tracking, the fullsave/create/update/deletelifecycle, timestamps, and mass assignment (fillable/guarded). - Every relation type -
HasOne,HasMany,BelongsTo,BelongsToMany(withattach/detach/sync),HasManyThrough, and polymorphicMorphOne/MorphMany/MorphTo. Lazy accessors, eager loading, and dot-nested eager loading (with("posts.comments")). - Existence & aggregates -
has,doesnt_have,where_has,with_count. - Soft deletes - the full lifecycle: scoped queries,
with_trashed/only_trashed,restore,force_delete. - Scopes & events - local scopes (extension traits +
.scoped()), global scopes, and typed observers with halting before-hooks. - Query builder - the where family, joins, group/having, unions, aggregates, upsert, JSON path selectors, and full-text search, compiled by per-dialect grammars.
- Schema & migrations - a fluent
Blueprint, aMigrator, and an embedded CLI (migrate,migrate:rollback,migrate:status,make:model,make:migration). - Factories & seeders, plus a synchronous [
blocking] facade for scripts.
[dependencies]
ferroquent = "0.0.1"
tokio = { version = "1", features = ["full"] }Default features include the mysql driver (which also serves MariaDB), chrono, schema,
migrations, and cli. PostgreSQL is provided by ferroquent-postgres with its driver feature.
| Crate | Role |
|---|---|
ferroquent |
Facade: prelude, re-exports, Ferroquent::boot, derive macros, blocking facade |
ferroquent-core |
Value, bindings, query AST, Grammar/Connection traits, driver registry |
ferroquent-model |
Model layer: Model, Builder<M>, relations, casts, scopes, observers |
ferroquent-macros |
#[derive(Model)] and #[derive(MorphTarget)] |
ferroquent-inflect |
English inflection, used at macro-expansion time |
ferroquent-mysql |
The sqlx-backed MySQL/MariaDB driver (grammar + connection) |
ferroquent-postgres |
PostgreSQL: a core-only grammar, plus a live driver behind --features driver |
ferroquent-schema |
Fluent schema builder and DDL grammar |
ferroquent-migrations |
Migration trait, Migrator, the migrations table |
ferroquent-cli |
Embedded CLI runtime (migrate + scaffolding) |
The driver seam is real: ferroquent-postgres depends on ferroquent-core alone by default - a
new backend is a self-contained crate, exactly like Laravel's driver packages.
Unit and grammar golden tests need no database:
cargo test --workspaceIntegration tests run against live servers (see docker-compose.yml):
docker compose up -d
export FERROQUENT_TEST_MYSQL_DSN=mysql://root:secret@127.0.0.1:33061/ferroquent_test
export FERROQUENT_TEST_MARIADB_DSN=mysql://root:secret@127.0.0.1:33062/ferroquent_test
export FERROQUENT_TEST_PG_DSN=postgres://postgres:secret@127.0.0.1:33063/ferroquent_test
cargo test --workspace --all-features
cargo test -p ferroquent-postgres --features driverFerroquent mirrors Eloquent's behavior closely; where Rust's type system forces a different shape
(no property interception, no runtime reflection), the divergence is intentional and documented in
docs/DEVIATIONS.md.
MIT - see LICENSE.