Inject some builders in script

Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
Lee Smet
2025-04-04 15:59:30 +02:00
parent 04233e6f1a
commit 53d8d184c4
8 changed files with 404 additions and 190 deletions

View File

@@ -1,13 +1,12 @@
use chrono::{DateTime, Utc, Duration};
use chrono::{DateTime, Duration, Utc};
use herodb::db::{DB, DBBuilder};
use herodb::models::biz::{
Currency, CurrencyBuilder,
Product, ProductBuilder, ProductComponent, ProductComponentBuilder,
ProductType, ProductStatus,
Sale, SaleBuilder, SaleItem, SaleItemBuilder, SaleStatus
Currency, CurrencyBuilder, Product, ProductBuilder, ProductComponent, ProductComponentBuilder,
ProductStatus, ProductType, Sale, SaleBuilder, SaleItem, SaleItemBuilder, SaleStatus,
};
use std::path::PathBuf;
use rhai::{Engine, packages::Package};
use std::fs;
use std::path::PathBuf;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("DB Example 2: Using Builder Pattern and Model-Specific Methods");
@@ -21,25 +20,170 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
fs::create_dir_all(&db_path)?;
println!("Database path: {:?}", db_path);
let mut engine = Engine::new();
engine
.build_type::<Product>()
.build_type::<ProductBuilder>()
.build_type::<ProductComponentBuilder>()
.build_type::<Currency>()
.build_type::<CurrencyBuilder>()
.build_type::<Sale>()
.build_type::<SaleBuilder>()
.build_type::<DBBuilder>()
.build_type::<DB>();
// Register currency builder methods
engine.register_fn("new_currency_builder", CurrencyBuilder::new);
engine.register_fn("amount", CurrencyBuilder::amount);
engine.register_fn("currency_code", CurrencyBuilder::currency_code::<String>);
engine.register_fn("build", CurrencyBuilder::build);
// Register method to verify currency
engine.register_fn("amount", Currency::amount);
// Register product component builder methods
engine.register_fn(
"new_product_component_builder",
ProductComponentBuilder::new,
);
engine.register_fn("id", ProductComponentBuilder::id);
engine.register_fn("name", ProductComponentBuilder::name::<String>);
engine.register_fn(
"description",
ProductComponentBuilder::description::<String>,
);
engine.register_fn("quantity", ProductComponentBuilder::quantity);
engine.register_fn("build", ProductComponentBuilder::build);
// Register product builder methods
engine.register_fn("new_product_builder", ProductBuilder::new);
engine.register_fn("id", ProductBuilder::id);
engine.register_fn("name", ProductBuilder::name::<String>);
engine.register_fn("description", ProductBuilder::description::<String>);
engine.register_fn("price", ProductBuilder::price);
engine.register_fn("type", ProductBuilder::type_);
engine.register_fn("category", ProductBuilder::category::<String>);
engine.register_fn("status", ProductBuilder::status);
engine.register_fn("max_amount", ProductBuilder::max_amount);
engine.register_fn("validity_days", ProductBuilder::validity_days);
engine.register_fn("add_component", ProductBuilder::add_component);
engine.register_fn("build", ProductBuilder::build);
// Register db builder methods
engine.register_fn("new_db_builder", DBBuilder::new::<String>);
engine.register_fn("register_currency", DBBuilder::register_model::<Currency>);
engine.register_fn("register_product", DBBuilder::register_model::<Product>);
engine.register_fn("register_sale", DBBuilder::register_model::<Sale>);
engine.register_fn("currency_code", CurrencyBuilder::currency_code::<String>);
engine.register_fn("build", DBBuilder::build);
// Register db methods
engine.register_fn("insert_currency", DB::insert_currency);
engine.register_fn("insert_product", DB::insert_product);
let script = r#"
let usd = new_currency_builder()
.amount(0.0)
.currency_code("USD")
.build();
// Can we access and print this from the actual Currency?
print(usd.amount());
let db = new_db_builder("./tmp/dbexample2")
.register_product()
.register_currency()
.register_sale()
.build();
db.insert_currency(usd);
let component1 = new_product_component_builder()
.id(101)
.name("Basic Support")
.description("24/7 email support")
.quantity(1)
.build();
let component2 = new_product_component_builder()
.id(102)
.name("Premium Support")
.description("24/7 phone and email support")
.quantity(1)
.build();
// Create products using the builder
// let product1 = new_product_builder()
// .id(1)
// .name("Standard Plan")
// .description("Our standard service offering")
// .price(
// new_currency_builder()
// .amount(29.99)
// .currency_code("USD")
// .build()
// )
// .type_(ProductType::Service)
// .category("Subscription")
// .status(ProductStatus::Available)
// .max_amount(1000)
// .validity_days(30)
// .add_component(component1)
// .build();
//
// let product2 = new_product_builder()
// .id(2)
// .name("Premium Plan")
// .description("Our premium service offering with priority support")
// .price(
// new_currency_builder()
// .amount(99.99)
// .currency_code("USD")
// .build()
// )
// .type_(ProductType::Service)
// .category("Subscription")
// .status(ProductStatus::Available)
// .max_amount(500)
// .validity_days(30)
// .add_component(component2)
// .build();
// Insert products using model-specific methods
// db.insert_product(product1);
// db.insert_product(product2);
"#;
engine.eval::<()>(script)?;
// Create a database instance with our models registered
let db = DBBuilder::new(&db_path)
let mut db = DBBuilder::new(&db_path)
.register_model::<Product>()
.register_model::<Currency>()
.register_model::<Sale>()
.build()?;
// Check if the currency created in the script is actually present, if it is this value should
// be 1 (NOTE: it will be :) ).
let currencies = db.list_currencies()?;
println!("Found {} currencies in db", currencies.len());
for currency in currencies {
println!("{} {}", currency.amount, currency.currency_code);
}
println!("\n1. Creating Products with Builder Pattern");
println!("----------------------------------------");
// Create a currency using the builder
let usd = CurrencyBuilder::new()
.amount(0.0) // Initial amount
.currency_code("USD")
.build()?;
// Insert the currency
db.insert_currency(&usd)?;
println!("Currency created: ${:.2} {}", usd.amount, usd.currency_code);
// // Create a currency using the builder
// let usd = CurrencyBuilder::new()
// .amount(0.0) // Initial amount
// .currency_code("USD")
// .build()?;
//
// // Insert the currency
// db.insert_currency(usd.clone())?;
// println!("Currency created: ${:.2} {}", usd.amount, usd.currency_code);
// Create product components using the builder
let component1 = ProductComponentBuilder::new()
@@ -55,16 +199,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.description("24/7 phone and email support")
.quantity(1)
.build()?;
// Create products using the builder
let product1 = ProductBuilder::new()
.id(1)
.name("Standard Plan")
.description("Our standard service offering")
.price(CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()?)
.price(
CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()?,
)
.type_(ProductType::Service)
.category("Subscription")
.status(ProductStatus::Available)
@@ -77,10 +222,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.id(2)
.name("Premium Plan")
.description("Our premium service offering with priority support")
.price(CurrencyBuilder::new()
.amount(99.99)
.currency_code("USD")
.build()?)
.price(
CurrencyBuilder::new()
.amount(99.99)
.currency_code("USD")
.build()?,
)
.type_(ProductType::Service)
.category("Subscription")
.status(ProductStatus::Available)
@@ -90,18 +237,27 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.build()?;
// Insert products using model-specific methods
db.insert_product(&product1)?;
db.insert_product(&product2)?;
db.insert_product(product1.clone())?;
db.insert_product(product2.clone())?;
println!("Product created: {} (${:.2})", product1.name, product1.price.amount);
println!("Product created: {} (${:.2})", product2.name, product2.price.amount);
println!(
"Product created: {} (${:.2})",
product1.name, product1.price.amount
);
println!(
"Product created: {} (${:.2})",
product2.name, product2.price.amount
);
println!("\n2. Retrieving Products");
println!("--------------------");
// Retrieve products using model-specific methods
let retrieved_product1 = db.get_product(1)?;
println!("Retrieved: {} (${:.2})", retrieved_product1.name, retrieved_product1.price.amount);
println!(
"Retrieved: {} (${:.2})",
retrieved_product1.name, retrieved_product1.price.amount
);
println!("Components:");
for component in &retrieved_product1.components {
println!(" - {} ({})", component.name, component.description);
@@ -114,10 +270,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let all_products = db.list_products()?;
println!("Found {} products:", all_products.len());
for product in all_products {
println!(" - {} (${:.2}, {})",
product.name,
println!(
" - {} (${:.2}, {})",
product.name,
product.price.amount,
if product.is_purchasable() { "Available" } else { "Unavailable" }
if product.is_purchasable() {
"Available"
} else {
"Unavailable"
}
);
}
@@ -126,17 +287,19 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a sale using the builder
let now = Utc::now();
let item1 = SaleItemBuilder::new()
.id(201)
.sale_id(1)
.product_id(1)
.name("Standard Plan")
.quantity(1)
.unit_price(CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()?)
.unit_price(
CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()?,
)
.active_till(now + Duration::days(30))
.build()?;
@@ -151,11 +314,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.build()?;
// Insert the sale using model-specific methods
db.insert_sale(&sale)?;
println!("Sale created: #{} for {} (${:.2})",
sale.id,
sale.buyer_name,
sale.total_amount.amount
db.insert_sale(sale.clone())?;
println!(
"Sale created: #{} for {} (${:.2})",
sale.id, sale.buyer_name, sale.total_amount.amount
);
println!("\n5. Updating a Sale");
@@ -163,12 +325,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Retrieve the sale, update it, and save it back
let mut retrieved_sale = db.get_sale(1)?;
println!("Retrieved sale: #{} with status {:?}", retrieved_sale.id, retrieved_sale.status);
println!(
"Retrieved sale: #{} with status {:?}",
retrieved_sale.id, retrieved_sale.status
);
// Update the status
retrieved_sale.update_status(SaleStatus::Completed);
db.insert_sale(&retrieved_sale)?;
db.insert_sale(retrieved_sale.clone())?;
println!("Updated sale status to {:?}", retrieved_sale.status);
println!("\n6. Deleting Objects");
@@ -187,4 +352,4 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\nExample completed successfully!");
Ok(())
}
}