Attribute Macro ruva_macro::aggregate
source · #[aggregate]Expand description
Define Aggregate root
§Example
#[aggregate]
pub struct TestAggregate {
pub(crate) age: i64,
}
fn test_aggregate() {
let aggregate = TestAggregate::default().set_age(1);
assert_eq!(aggregate.version, 0);
assert!(!aggregate.is_existing);
assert_eq!(aggregate.events.len(), 0);
assert_eq!(aggregate.age, 1)
}#[aggregate]
pub struct TestAggregate {
pub(crate) age: i64,
pub(crate) name: String,
}Likewise, not specifying identifier will also error out
#[aggregate]
pub struct TestAggregate {
pub(crate) age: i64,
pub(crate) name: String,
}{your aggregate name}Adapter will be generated automatically so you can use it to adapt it to database
rust,no_run
#[aggregate] pub struct AggregateStruct { #[adapter_ignore] id: i32, #[serde(skip_serializing)] name: String, some_other_field: i32, } let aggregate = AggregateStruct::default(); let serialized = serde_json::to_string(&aggregate).unwrap(); assert_eq!(serialized, “{"id":0,"some_other_field":0,"version":0}”);
let adapter = AggregateStructAdapter::default(); let serialized = serde_json::to_string(&adapter).unwrap(); assert_eq!(serialized, “{"some_other_field":0}”);
# Automatic derive macro
`#[derive(Default, Debug, Serialize, Deserialize)]` will be automatically added to the struct.
```rust,no_run
#[aggregate]
pub struct AggregateStruct {
#[adapter_ignore]
id: i32,
#[serde(skip_serializing)]
name: String,
some_other_field: i32,
}Even if you add Default, Debug, Serialize, Deserialize there won’t be any conflict.
Conversion is automatically done as follows:
rust,no_run
let aggregate = AggregateStruct {
name: “migo”.into(),
some_other_field: 2,
id: 1,
..Default::default()
};
let converted_adapter = AggregateStructAdapter::from(aggregate);
assert_eq!(converted_adapter.name, “migo”);
assert_eq!(converted_adapter.some_other_field, 2);
let converted_struct = AggregateStruct::from(converted_adapter);
assert_eq!(converted_struct.name, “migo”);
assert_eq!(converted_struct.some_other_field, 2);
Generic can also be used for aggregate:
```rust,no_run
#[derive(Default, Debug, Serialize, Deserialize)]
struct Unset;
#[aggregate]
#[derive(Default, Debug, Serialize, Clone)]
struct MyStruct<T = Unset>
where
T: Send + Sync + Default + 'static,
{
name: String,
age: i32,
#[adapter_ignore]
sub_type: T,
}
impl MyStruct<String> {
fn do_something_with_string(&self) -> String {
self.sub_type.clone()
}
}
impl MyStruct<i32> {
fn do_something_with_i32(&self) -> i32 {
self.sub_type
}
}
let adapter = MyStructAdapter {
name: "hello".to_string(),
age: 10,
};
let _my_unset_struct = Into::<MyStruct>::into(adapter.clone()); // default type is set which has no method attached.
let my_string_struct = Into::<MyStruct<String>>::into(adapter.clone());
let my_int32_struct = Into::<MyStruct<i32>>::into(adapter.clone());
assert_eq!(my_string_struct.do_something_with_string(), String::default());
assert_eq!(my_int32_struct.do_something_with_i32(), i32::default());