parse_rs/
relations.rs

1use crate::error::ParseError;
2use crate::types::RelationOp; // For types not directly re-exported at crate root like RelationOp
3use crate::{ParseDate, Pointer};
4
5use reqwest::Method;
6use serde::Deserialize;
7
8impl crate::Parse {
9    /// Adds target objects to a relation field of a parent object.
10    ///
11    /// # Arguments
12    /// * `parent_class_name`: The class name of the parent object.
13    /// * `parent_object_id`: The object ID of the parent object.
14    /// * `relation_key`: The key (field name) of the relation on the parent object.
15    /// * `targets`: A slice of `Pointer`s representing the objects to add to the relation.
16    ///
17    /// # Returns
18    /// A `Result` containing the `ParseDate` of the update or a `ParseError`.
19    /// This operation typically requires the Master Key or appropriate ACLs.
20    pub async fn add_to_relation(
21        &self,
22        parent_class_name: &str,
23        parent_object_id: &str,
24        relation_key: &str,
25        targets: &[Pointer],
26    ) -> Result<ParseDate, ParseError> {
27        if targets.is_empty() {
28            return Err(ParseError::InvalidInput(
29                "targets cannot be empty for AddRelation operation.".to_string(),
30            ));
31        }
32        if parent_class_name.is_empty() || parent_object_id.is_empty() || relation_key.is_empty() {
33            return Err(ParseError::InvalidInput(
34                "parent_class_name, parent_object_id, and relation_key cannot be empty."
35                    .to_string(),
36            ));
37        }
38
39        let endpoint = format!("classes/{}/{}", parent_class_name, parent_object_id);
40        let relation_op = RelationOp::add(targets);
41        let body = serde_json::json!({ relation_key: relation_op });
42
43        let use_master_key = self.master_key.is_some();
44        let session_token_to_use = if use_master_key {
45            None
46        } else {
47            self.session_token.as_deref()
48        };
49
50        #[derive(Deserialize)]
51        struct UpdateResponse {
52            #[serde(rename = "updatedAt")]
53            updated_at: String,
54        }
55
56        let response: UpdateResponse = self
57            ._request(
58                Method::PUT,
59                &endpoint,
60                Some(&body),
61                use_master_key,
62                session_token_to_use,
63            )
64            .await?;
65
66        Ok(ParseDate::new(response.updated_at))
67    }
68
69    /// Removes target objects from a relation field of a parent object.
70    ///
71    /// # Arguments
72    /// * `parent_class_name`: The class name of the parent object.
73    /// * `parent_object_id`: The object ID of the parent object.
74    /// * `relation_key`: The key (field name) of the relation on the parent object.
75    /// * `targets`: A slice of `Pointer`s representing the objects to remove from the relation.
76    ///
77    /// # Returns
78    /// A `Result` containing the `ParseDate` of the update or a `ParseError`.
79    /// This operation typically requires the Master Key or appropriate ACLs.
80    pub async fn remove_from_relation(
81        &self,
82        parent_class_name: &str,
83        parent_object_id: &str,
84        relation_key: &str,
85        targets: &[Pointer],
86    ) -> Result<ParseDate, ParseError> {
87        if targets.is_empty() {
88            return Err(ParseError::InvalidInput(
89                "targets cannot be empty for RemoveRelation operation.".to_string(),
90            ));
91        }
92        if parent_class_name.is_empty() || parent_object_id.is_empty() || relation_key.is_empty() {
93            return Err(ParseError::InvalidInput(
94                "parent_class_name, parent_object_id, and relation_key cannot be empty."
95                    .to_string(),
96            ));
97        }
98
99        let endpoint = format!("classes/{}/{}", parent_class_name, parent_object_id);
100        let relation_op = RelationOp::remove(targets);
101        let body = serde_json::json!({ relation_key: relation_op });
102
103        let use_master_key = self.master_key.is_some();
104        let session_token_to_use = if use_master_key {
105            None
106        } else {
107            self.session_token.as_deref()
108        };
109
110        #[derive(Deserialize)]
111        struct UpdateResponse {
112            #[serde(rename = "updatedAt")]
113            updated_at: String,
114        }
115
116        let response: UpdateResponse = self
117            ._request(
118                Method::PUT,
119                &endpoint,
120                Some(&body),
121                use_master_key,
122                session_token_to_use,
123            )
124            .await?;
125
126        Ok(ParseDate::new(response.updated_at))
127    }
128}