Skip to content

Commit ad765ed

Browse files
Pollepsjoepio
authored andcommitted
Destroy children when deleting resource
1 parent eadadd2 commit ad765ed

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ See [STATUS.md](server/STATUS.md) to learn more about which features will remain
1616
- Refactor `for_agent` arguments to use the new `ForAgent` enum #623
1717
- Add support for Bearer token authentication, find in `/app/token` #632
1818
- Add a `query` endpoint that allows peroforming collection queries via an enpoint instead of repurposing the collections collection.
19+
- `resource.destroy` now recursively destroys its children.
1920

2021
## [v0.34.2] - 2023-03-04
2122

lib/src/resources.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! Has methods for saving resources and getting properties inside them.
33
44
use crate::commit::{CommitOpts, CommitResponse};
5+
use crate::storelike::Query;
56
use crate::urls;
67
use crate::utils::random_string;
78
use crate::values::{SubResource, Value};
@@ -47,15 +48,30 @@ impl Resource {
4748
}
4849

4950
/// Removes / deletes the resource from the store by performing a Commit.
51+
/// Recursively deletes the resource's children.
5052
pub fn destroy(
5153
&mut self,
5254
store: &impl Storelike,
5355
) -> AtomicResult<crate::commit::CommitResponse> {
56+
let children = self.get_children(store);
57+
58+
if let Ok(children) = children {
59+
for mut child in children {
60+
child.destroy(store)?;
61+
}
62+
}
63+
5464
self.commit.destroy(true);
5565
self.save(store)
5666
.map_err(|e| format!("Failed to destroy {} : {}", self.subject, e).into())
5767
}
5868

69+
/// Gets the children of this resource.
70+
pub fn get_children(&self, store: &impl Storelike) -> AtomicResult<Vec<Resource>> {
71+
let result = store.query(&Query::new_prop_val(urls::PARENT, self.get_subject()))?;
72+
Ok(result.resources)
73+
}
74+
5975
pub fn from_propvals(propvals: PropVals, subject: String) -> Resource {
6076
Resource {
6177
propvals,
@@ -544,6 +560,8 @@ impl Resource {
544560

545561
#[cfg(test)]
546562
mod test {
563+
use ntest::assert_panics;
564+
547565
use super::*;
548566
use crate::{test_utils::init_store, urls};
549567

@@ -772,4 +790,78 @@ mod test {
772790
.unwrap();
773791
assert_eq!(new_val.first().unwrap(), append_value);
774792
}
793+
794+
#[test]
795+
fn get_children() {
796+
let store = init_store();
797+
let mut resource1 = Resource::new_generate_subject(&store);
798+
let subject1 = resource1.get_subject().to_string();
799+
resource1.save_locally(&store).unwrap();
800+
801+
let mut resource2 = Resource::new_generate_subject(&store);
802+
resource2
803+
.set_propval(urls::PARENT.into(), Value::AtomicUrl(subject1), &store)
804+
.unwrap();
805+
let subject2 = resource2.get_subject().to_string();
806+
resource2.save_locally(&store).unwrap();
807+
808+
let children = resource1.get_children(&store).unwrap();
809+
810+
assert_eq!(children.len(), 1);
811+
assert_eq!(children[0].get_subject(), &subject2);
812+
}
813+
814+
#[test]
815+
fn destroy() {
816+
let store = init_store();
817+
// Create 3 resources in a tree structure.
818+
819+
let mut resource1 = Resource::new_generate_subject(&store);
820+
let subject1 = resource1.get_subject().to_string();
821+
resource1.save_locally(&store).unwrap();
822+
823+
let mut resource2 = Resource::new_generate_subject(&store);
824+
resource2
825+
.set_propval(
826+
urls::PARENT.into(),
827+
Value::AtomicUrl(subject1.clone()),
828+
&store,
829+
)
830+
.unwrap();
831+
let subject2 = resource2.get_subject().to_string();
832+
resource2.save_locally(&store).unwrap();
833+
834+
let mut resource3 = Resource::new_generate_subject(&store);
835+
resource3
836+
.set_propval(
837+
urls::PARENT.into(),
838+
Value::AtomicUrl(subject2.clone()),
839+
&store,
840+
)
841+
.unwrap();
842+
let subject3 = resource3.get_subject().to_string();
843+
resource3.save_locally(&store).unwrap();
844+
845+
// Check if all 3 resources exist in the store.
846+
847+
assert_eq!(
848+
store.get_resource(&subject1).unwrap().get_subject(),
849+
&subject1
850+
);
851+
assert_eq!(
852+
store.get_resource(&subject2).unwrap().get_subject(),
853+
&subject2
854+
);
855+
assert_eq!(
856+
store.get_resource(&subject3).unwrap().get_subject(),
857+
&subject3
858+
);
859+
860+
// Destroy the first resource, and check if all 3 resources are gone.
861+
resource1.destroy(&store).unwrap();
862+
863+
assert_panics!({ store.get_resource(&subject1).unwrap() });
864+
assert_panics!({ store.get_resource(&subject2).unwrap() });
865+
assert_panics!({ store.get_resource(&subject3).unwrap() });
866+
}
775867
}

lib/src/storelike.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ pub struct Query {
353353
pub property: Option<String>,
354354
/// Filter by Value
355355
pub value: Option<Value>,
356-
/// Maximum of items to return
356+
/// Maximum of items to return, if none returns all items.
357357
pub limit: Option<usize>,
358358
/// Value at which to begin lexicographically sorting things.
359359
pub start_val: Option<Value>,

0 commit comments

Comments
 (0)