ActiveRecord pattern for Rust based on SQLx. Write idiomatic DB code (Postgres only).
[dependencies]
sqlx-models-orm = "0.1"Read the in-depth tutorial that doubles as a "kitchen sink" test in the examples
These are just some of the time-saving, boilerplate-killing features:
model!{
state:App,
table: humans,structHuman{
#[sqlx_model_hints(int4,default)]
id:i32,
#[sqlx_model_hints(varchar)]
name:String,
#[sqlx_model_hints(int4)]
age:Option<i32>,
#[sqlx_model_hints(boolean,default)]
is_allowed_unlimited_cats:bool,
#[sqlx_model_hints(boolean)]
likes_dogs_too:bool,},
has_many {Cat(human_id),}}let alice = app.human().insert(InsertHuman{name:"Alice".to_string(),age:Some(19),likes_dogs_too:true,}).save().await?;assert_eq!(alice.attrs,HumanAttrs{
id:1,
name:"Alice".to_string(),
age:Some(19),
is_allowed_unlimited_cats:false,
likes_dogs_too:true,});let some_humans = app.human().select().limit(2).offset(1).likes_dogs_too_eq(false).order_by(HumanOrderBy::Name).desc(true).all().await?;assert_eq!(some_humans, vec![alice]);let updated_alice = alice.update().use_struct(UpdateHuman{name:Some("Alice Alison".to_string()),age:Some(None),is_allowed_unlimited_cats:Some(true),
..Default::default()}).save().await?;assert_eq!(updated_alice.attrs,HumanAttrs{
id:1,
name:"Alice Alison".to_string(),
age:None,
is_allowed_unlimited_cats:true,
likes_dogs_too:true,}); alice.delete().await?;- Stateful: You're not supposed to be passing a connection pool around explicitly.
- Your structs, your abstractions: This crate has a proc macro that creates a number of structs for different operations on a single database table. You can add any methods you want to any of these structs. Structs for the same operation in different tables implement a common trait to allow some degree of generalization across operations in these tables.
- Idiomatic rather than performant: This should be easy to learn and use, even if there were performance tradeoffs.
- Fallaback to SQLx: Always make it possible to fall back for custom queries and performance enhancements.
- One table per query. Reinventing SQL for joining tables in the ORM is hard to debug and understand. Favour multiple single-table queries over a single multi-table one. (see previous item).
- Only compile time checked queries. No chance of sql injection, no need for silly tests, at the cost of longer queries.
- Only Postgres for now. Sorry about that :(