#object-oriented #serialize-deserialize #class #design #sdk #derive-debug #development

scaffolding-core

A software development kit that provides the scaffolding for building applications and services using OOP

13 releases (2 stable)

2.0.0 Jun 30, 2024
1.0.0 Jun 21, 2024
0.8.0 Jun 19, 2024
0.4.0 Mar 31, 2024

#296 in Rust patterns

41 downloads per month

Apache-2.0

76KB
503 lines

License Docs.rs Build/Test Discussions

Scaffolding Core

For software development teams who appreciate a kick-start to their object oriented development, this scaffolding library is a light-weight module that provides the basic structures and behavior that is the building block of all class intantiated objects. Unlike the practice of writing classes with the various approaches for building common functionality, this open source library helps you inherit these cross-class commonalities so you can focus on the differentiator that define your class.


Table of Contents


What's New

We made the crate easier to implement and updated the documentation and the crate metadata.

2.0.0

Usage

(1) Import the necessary modules

extern crate scaffolding_core;

use scaffolding_core::*;

(2) Add Scaffolding attributes and apply the trait to a struct

#[scaffolding_struct]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding)]
struct MyEntity {
    a: bool,
    b: String,
}

(3) Dynamically add the default values for the Scaffodling attributes as part of the impl ::new() constructor NOTE: The scaffolding_core::defaults module is available if you wish to use it else where

impl MyEntity {
    // Define the constructor - Optional
    // Note: Any of the Scaffolding attributes that are set here 
    //       will not be overwritten when generated. For example
    //       the `id` attribute, if uncommented, would be ignored.
    #[scaffolding_fn]
    fn new(arg: bool) -> Self {
        let msg = format!("You said it is {}", arg);
        Self {
            // id: "my unique identitifer".to_string(),
            a: arg,
            b: msg
        }
    }

    fn my_func(&self) -> String {
        "my function".to_string()
    }
}

(4) Use the Scaffolding attributes and behavior

let mut entity = MyEntity::new(true);

/* scaffolding attributes */
assert_eq!(entity.id.len(), "54324f57-9e6b-4142-b68d-1d4c86572d0a".len());
assert_eq!(entity.created_dtm, defaults::now());
assert_eq!(entity.modified_dtm, defaults::now());
// becomes inactive in 90 days
assert_eq!(entity.inactive_dtm, defaults::add_days(defaults::now(), 90));
// expires in 3 years
assert_eq!(entity.expired_dtm, defaults::add_years(defaults::now(), 3));

/* use the activity log functionality  */
// (1) Log an activity
entity.log_activity("cancelled".to_string(), "The customer has cancelled their service".to_string());
// (2) Get activities
assert_eq!(entity.get_activity("cancelled".to_string()).len(), 1);

/* custom attributes */
assert_eq!(entity.a, true);
assert_eq!(entity.b, "You said it is true");

/* custom behavior */
assert_eq!(entity.my_func(), "my function");

Serializing

let json_string = entity.serialize();
println!("{}", json_string);

Deserializing

let json = r#"{
    "id":"b4d6c6db-7468-400a-8536-a5e83b1f2bdc",
    "created_dtm":1711802687,
    "modified_dtm":1711802687,
    "inactive_dtm":1719578687,
    "expired_dtm":1806410687,
    "activity":[
        {
            "created_dtm":1711802687,
            "action":"updated",
            "description":"The object has been updated"
        },
        {
            "created_dtm":1711802687,
            "action":"updated",
            "description":"The object has been updated"
        },
        {
            "created_dtm":1711802687,
            "action":"cancelled",
            "description":"The object has been cancelled"
        }
        ]
    }"#;
let entity = MyEntity::deserialized(json.as_bytes()).unwrap();

assert_eq!(entity.get_activity("cancelled".to_string()).len(), 1);

There are additional Scaffolding features that can be applied.

Addresses

#[scaffolding_struct("addresses")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding, ScaffoldingAddresses)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("addresses")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

/* use the addresses functionality */
// (1) Add an address
let id = entity.add_address(
    "shipping".to_string(),
    "acmes company".to_string(),
    "14 Main Street".to_string(),
    "Big City, NY 038845".to_string(),
    "USA".to_string(),
    "USA".to_string(),
);
// (2) Find addresses based on the category
let shipping_addresses = entity.addresses_by_category("shipping".to_string());
// (3) Remove an address
entity.remove_address(id);

Email Addresses

#[scaffolding_struct("email_addresses")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding, ScaffoldingEmailAddresses)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("email_addresses")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

/* use the email addresses functionality */
// (1) Add an email address
let id = entity.insert_email_address(
    "home".to_string(),
    "myemail@example.com".to_string(),
);
// (2) Find email addresses based on the category
let home_email_addresses = entity.search_email_addresses_by_category("home".to_string());
// (3) Remove an address
entity.remove_address(id);

Metadata

#[scaffolding_struct("metadata")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("metadata")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

/* use the metadata functionality
   Note: `memtadata` is a BTreeMap<String, String>
          https://doc.rust-lang.org/std/collections/struct.BTreeMap.html
*/
entity.metadata.insert("field_1".to_string(), "myvalue".to_string());
assert_eq!(entity.metadata.len(), 1);

Notes

#[scaffolding_struct("notes")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding, ScaffoldingNotes)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("notes")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

// (1) Insert a note
let id = entity.insert_note(
  "fsmith".to_string(),
  "This was updated".as_bytes().to_vec(),
  None,
);
// (2) Modify the note
entity.modify_note(
  id.clone(),
  "fsmith".to_string(),
  "This was updated again".as_bytes().to_vec(),
  Some("private".to_string()),
);
// (3) Read the note's content
let read_note = entity.get_note(id.clone()).unwrap().content_as_string().unwrap();
println!("{}", read_note);
// (4) Search for notes that contain the word `updated`
let search_results = entity.search_notes("updated".to_string());
assert_eq!(search_results.len(), 1);
// (5) Delete the note
entity.remove_note(id);

Phone Numbers

#[scaffolding_struct("phone_numbers")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding, ScaffoldingPhoneNumbers)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("phone_numbers")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

/* use the phone number functionality */
// (1) Add a phone number
let _ = entity.add_phone_number(
    "home".to_string(),
    "8482493561".to_string(),
    "USA".to_string(),
);
let id = entity.add_phone_number(
    "work".to_string(),
    "2223330000".to_string(),
    "USA".to_string(),
);
// (2) Find phone number based on the category
let home_phone = entity.phone_numbers_by_category("home".to_string());
// (3) Remove an address
entity.remove_phone_number(id);

Tagging

#[scaffolding_struct("tags")]
#[derive(Debug, Clone, Deserialize, Serialize, Scaffolding, ScaffoldingTags)]
struct MyEntity {}

impl MyEntity {
    #[scaffolding_fn("tags")]
    fn new() -> Self {
        Self {}
    }
}

let mut entity = MyEntity::new();

// manage tags
entity.add_tag("tag_1".to_string());
entity.add_tag("tag_2".to_string());
entity.add_tag("tag_3".to_string());
assert!(entity.has_tag("tag_1".to_string()));
entity.remove_tag("tag_2".to_string());
assert_eq!(entity.tags.len(), 2);

How to Contribute

Details on how to contribute can be found in the CONTRIBUTING file.

License

The scaffolding-core project is primarily distributed under the terms of the Apache License (Version 2.0).

See LICENSE-APACHE "Apache License for details.

Dependencies

~4–6MB
~111K SLoC