Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ license = "Apache-2.0"
name = "scaffolding-core"
readme = "README.md"
repository = "https://github.com/dsietz/scaffolding-core"
version = "0.0.1"
version = "0.0.2"

[badges]
maintenance = {status = "experimental"}
Expand All @@ -26,7 +26,7 @@ path = "src/lib.rs"

[dependencies]
chrono = "0.4.35"
scaffolding-macros = {path = "./scaffolding-macros", version = "0.0.1"}
scaffolding-macros = {path = "./scaffolding-macros", version = "0.0.2"}

[dependencies.uuid]
features = ["v4"]
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Docs.rs](https://docs.rs/scaffolding-core/badge.svg)](https://docs.rs/scaffolding-core)
![Build/Test](https://github.com/dsietz/scaffolding-core/actions/workflows/master.yaml/badge.svg)
[![Discussions](https://img.shields.io/github/discussions/dsietz/scaffolding-core)](https://github.com/dsietz/scaffolding-core/discussions)

# Scaffolding Core

Expand Down
2 changes: 1 addition & 1 deletion scaffolding-macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "scaffolding-macros"
version = "0.0.1"
version = "0.0.2"
authors = ["dsietz <davidsietz@yahoo.com>"]
edition = "2021"
readme = "README.md"
Expand Down
8 changes: 4 additions & 4 deletions scaffolding-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ fn impl_scaffolding(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
impl Scaffolding for #name {
fn hello(&self) {
println!("Hello, My name is {}!", stringify!(#name));
println!("My id is {}", self.id);
}
// fn hello(&self) {
// println!("Hello, My name is {}!", stringify!(#name));
// println!("My id is {}", self.id);
// }
}
};
gen.into()
Expand Down
85 changes: 74 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
// #[macro_use]
// use std::time::{SystemTime, UNIX_EPOCH};
//! Object-oriented programming (OOP) has been around since the 1960s and was first introduced in the late 1950s
//! in artificial intelligence by an MMIT group. It is no wonder then that over the years, the concept of objects
//! being represented by classes and attributes with inheritanted behavior.
//!
//! Rust addresses this design by providing structures, traits, and implementations. However, the native ability to
//! `extend` a class (like in other languages) makes OOP a bit of a challenge. To address this gap, `Scaffolding` utilizes
//! Rust's [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html) to mimic the ability to
//! `extend` a class - both data structure and behavior.
//!
//! ## Scaffolding Concept
//! I. A class that `extends` the "Scaffolding class" should inherate all the "parent" data structure and behavior,
//! as well as append the "child" specific data structure and behavior
//! II. The developer should have the flexibility to adopt the default "parent" characteristics or overwrite them as desired.
//! III. There are common class attributes that are required in order to manage it using CRUD
//! + `id` - The unique identifier of the object.
//! + `created_dtm` - The unix epoch (UTC) representation of when the object was created
//! + `modified_dtm` - The unix epoch (UTC) representation of when the object was last updated
//! + `inactive_dtm` - The unix epoch (UTC) representation of when the object was/will be considered obsolete
//! + `expired_dtm` - The unix epoch (UTC) representation of when the object was/will be ready for deletion
//! IV. There is common class behaviors that are required in order to manage it using CRUD
//! + The `id` is not optional. It must be either provided or automatically generated during instantiation.
//! This can be done by calling the `Scaffolding` trait's `id()` method
//! + The `created_dtm` is not optional. It must be either provided or automatically generated during instantiation.
//! This can be done by calling one of the `Scaffolding` trait's many datetime related methods, (e.g.: `now()`)
//! + The `modified_dtm` is not optional. It must be either provided or automatically generated during instantiation or updates to the object.
//! This can be done by calling one of the `Scaffolding` trait's many datetime related methods, (e.g.: `now()`)
//! + The `inactive_dtm` is not optional. It must be either provided or automatically generated during instantiation or updates to the object.
//! This can be done by calling one of the `Scaffolding` trait's many datetime related methods, (e.g.: `add_months()` in conjuctions with `now()`)
//! + The `expire_dtm` is not optional. It must be either provided or automatically generated during instantiation or updates to the object.
//! This can be done by calling one of the `Scaffolding` trait's many datetime related methods, (e.g.: `never()`)
//!
//! ### Example
//!
//! ```rust
//! extern crate scaffolding_core;
//!
//! use scaffolding_core::*;
//! use scaffolding_macros::*;
//!
//! #[as_entity]
//! #[derive(Debug, Clone, Scaffolding)]
//! struct MyEntity {
//! b: bool,
//! }
//!
//! impl MyEntity {
//! fn new(arg: bool) -> Self {
//! Self {
//! id: <Self as Scaffolding>::id(),
//! created_dtm: <Self as Scaffolding>::now(),
//! modified_dtm: <Self as Scaffolding>::now(),
//! inactive_dtm: <Self as Scaffolding>::add_months(<Self as Scaffolding>::now(), 12),
//! expired_dtm: <Self as Scaffolding>::add_years(<Self as Scaffolding>::now(), 3),
//! b: arg,
//! }
//! }
//!
//! fn my_func(&self) -> String {
//! "my function".to_string()
//! }
//! }
//!
//! let entity = MyEntity::new(true);
//! println!("{:?}", entity);
//!
//! // extended attributes
//! assert_eq!(entity.b, true);
//!
//! // extended behavior
//! assert_eq!(entity.my_func(), "my function");
//! ```

use chrono::{DateTime, Duration, Months, Utc};
use uuid::Uuid;

pub enum Intervals {
Year,
Month,
Day,
}

/// The core behavior of an Scaffolding object
pub trait Scaffolding {
fn hello(&self) {}

/// generates a uuid v4 value
fn id() -> String {
Uuid::new_v4().to_string()
Expand All @@ -23,7 +86,7 @@ pub trait Scaffolding {
dt.timestamp()
}

/// adds x years to the timestamp
/// adds x months to the timestamp
fn add_months(dtm: i64, months: u32) -> i64 {
let dt = DateTime::from_timestamp(dtm, 0).unwrap() + Months::new(months);
dt.timestamp()
Expand Down
25 changes: 9 additions & 16 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// #[macro_use]
extern crate scaffolding_core;
extern crate scaffolding_macros;

#[cfg(test)]
mod tests {
use chrono::{DateTime, Utc};
use chrono::Utc;
use scaffolding_core::*;
use scaffolding_macros::*;

Expand Down Expand Up @@ -34,26 +33,17 @@ mod tests {
}

// #[test]
// fn test_entity() {
// let entity = MyEntity {
// id: "lorem ipsum".to_string(),
// b: true,
// };
// assert_eq!(entity.id, "lorem ipsum");
// fn test_entity_hello() {
// let mut entity = MyEntity::new(true);
// entity.hello();
// assert_eq!(entity.my_func(), "my function");
// }

#[test]
fn test_entity_hello() {
let mut entity = MyEntity::new(true);
entity.hello();
assert_eq!(entity.my_func(), "my function");
}

#[test]
fn test_entity_new() {
let now = Utc::now().timestamp();
let never = 253402261199;
let mut entity = MyEntity::new(true);
let entity = MyEntity::new(true);

// scaffolding attributes
assert_eq!(
Expand All @@ -68,5 +58,8 @@ mod tests {
// extended attributes
assert_eq!(entity.b, true);
assert_eq!(entity.n, never);

// extended behavior
assert_eq!(entity.my_func(), "my function");
}
}