Entity Model
So we need to conveniently create a product
table objects,
but we don't want to re-populate all the fields and conditions
every time.
DORM recommends you to have a object called Product
that
would vend Table
objects. We will place the code inside
a model
subfolder.
While we are building our Product
type, lets also create
a static instance of our DataSource:
inside your model/mod.rs:
#![allow(unused)] fn main() { use dorm::prelude::Postgres; pub mod products; pub use products::*; static POSTGRESS: OnceLock<Postgres> = OnceLock::new(); pub fn set_postgres(postgres: Postgres) -> Result<()> { POSTGRESS .set(postgres) .map_err(|_| anyhow::anyhow!("Failed to set Postgres instance")) } pub fn postgres() -> Postgres { POSTGRESS .get() .expect("Postgres has not been initialized") .clone() } }
Now you would need to call set_postgress() when your tokio_postgress client is ready and you can import and call postgress() from your models.
Lets create file models/products.rs
:
#![allow(unused)] fn main() { use dorm::prelude::*; use crate::postgres; pub struct Product {} impl Product { pub fn table() -> Table<Postgres> { Product::static_table().clone() } pub fn static_table() -> &'static Table<Postgres> { static TABLE: OnceLock<Table<Postgres>> = OnceLock::new(); TABLE.get_or_init(|| { Table::new("product", postgres()) .with_id_field("id") .with_field("name") }) } pub fn name() -> Arc<Field> { Product::static_table().get_field("name").unwrap() } } }
Now that you have created a Product type, we can reference it in your application like this:
#![allow(unused)] fn main() { use model; let products = model::Product::table(); writeln!(products.get_select_query().preview()); // renders into: SELECT id, name FROM product let low_cal_products = model::Product::table() .with_condition( model::Products::calories().lt(100) ); writeln!(low_cal_products.get_select_query().preview()); // renders into: SELECT id, name, calories FROM product WHERE (calories < 100) }
This is already much more portable, but we can do better.
Add this to your model/products.rs
and
#![allow(unused)] fn main() { pub struct LowCalProduct {} impl LowCalProduct { pub fn table() -> Table<Postgres> { Product::table().with_condition( Product::calories().lt(100) ) } } }
You can addopt a different approach here, those are just a few recommendations. Later we will explore a way to create a dynamic business entity pattern, but now we will focus on something more fun - joins.