1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
use crate::query::{Query, RecordQueryResult}; use crate::{DatabaseAccess, DatabaseRecord, Record, ServiceError}; /// The `Link` trait of the Aragog library. /// It allows to define a query relation between different models. /// /// # Example /// /// ```rust /// # use aragog::{Record, Validate, Link, DatabaseConnectionPool, DatabaseRecord, AuthMode}; /// # use aragog::query::{Query, Comparison}; /// # use serde::{Deserialize, Serialize}; /// # use std::borrow::Borrow; /// # /// #[derive(Clone, Serialize, Deserialize, Record, Validate)] /// pub struct Order { /// pub content: String, /// pub user_id: String, /// } /// /// #[derive(Clone, Serialize, Deserialize, Record, Validate)] /// pub struct User {} /// /// impl Link<Order> for DatabaseRecord<User> { /// fn link_query(&self) -> Query { /// Order::query().filter(Comparison::field("user_id").equals_str(self.key()).into()) /// } /// } /// /// # #[tokio::main] /// # async fn main() { /// # let database_pool = DatabaseConnectionPool::builder() /// # .with_credentials( /// # &std::env::var("DB_HOST").unwrap_or("http://localhost:8529".to_string()), /// # &std::env::var("DB_NAME").unwrap_or("aragog_test".to_string()), /// # &std::env::var("DB_USER").unwrap_or("test".to_string()), /// # &std::env::var("DB_PWD").unwrap_or("test".to_string()) /// # ) /// # .with_schema_path("tests/schema.yaml") /// # .build() /// # .await /// # .unwrap(); /// # database_pool.truncate().await; /// let user = DatabaseRecord::create(User {}, &database_pool).await.unwrap(); /// let order = DatabaseRecord::create( /// Order { /// content: "content".to_string(), /// user_id: user.key().clone() /// }, /// &database_pool).await.unwrap(); /// let orders = user.linked_models(&database_pool).await.unwrap(); /// assert_eq!(user.key(), &orders.first().unwrap().user_id); /// # } /// ``` #[maybe_async::must_be_async] pub trait Link<T: Record>: Sized { /// Defines the query to execute to find the `T` models linked to `Self` /// /// # Example /// /// ```rust /// # use aragog::{Record, Validate, Link, DatabaseConnectionPool, DatabaseRecord}; /// # use aragog::query::{Query, Comparison}; /// # use serde::{Deserialize, Serialize}; /// # use std::borrow::Borrow; /// # /// #[derive(Clone, Serialize, Deserialize, Record, Validate)] /// pub struct Order { /// pub content: String, /// pub user_id: String, /// } /// /// #[derive(Clone, Serialize, Deserialize, Record, Validate)] /// pub struct User {} /// /// impl Link<Order> for DatabaseRecord<User> { /// fn link_query(&self) -> Query { /// Order::query().filter(Comparison::field("user_id").equals_str(self.key()).into()) /// } /// } ///``` fn link_query(&self) -> Query; /// Retrieves the records matching the defined `link_query`. Type inference may be required. #[cfg(feature = "async")] async fn linked_models<D>(&self, db_pool: &D) -> Result<RecordQueryResult<T>, ServiceError> where Self: Sized, D: DatabaseAccess, T: 'async_trait, { DatabaseRecord::get(self.link_query(), db_pool).await } /// Retrieves the records matching the defined `link_query`. Type inference may be required. #[cfg(not(feature = "async"))] fn linked_models<D>(&self, db_pool: &D) -> Result<RecordQueryResult<T>, ServiceError> where D: DatabaseAccess, { DatabaseRecord::get(self.link_query(), db_pool) } }