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, QueryResult};
use crate::{DatabaseAccess, DatabaseRecord, Error, Record};
/// The `Link` trait of the Aragog library.
/// It allows to define a query relation between different models.
///
/// # Example
///
/// ```rust
/// # use aragog::{Record, Validate, Link, DatabaseConnection, 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_connection = DatabaseConnection::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_PASSWORD").unwrap_or("test".to_string())
/// # )
/// # .with_schema_path("tests/schema.yaml")
/// # .build()
/// # .await
/// # .unwrap();
/// # database_connection.truncate().await;
/// let user = DatabaseRecord::create(User {}, &database_connection).await.unwrap();
/// let order = DatabaseRecord::create(
/// Order {
/// content: "content".to_string(),
/// user_id: user.key().clone()
/// },
/// &database_connection).await.unwrap();
/// let orders = user.linked_models(&database_connection).await.unwrap();
/// assert_eq!(user.key(), &orders.first().unwrap().user_id);
/// # }
/// ```
#[maybe_async::must_be_async]
pub trait Link<T: Record + Send> {
/// Defines the query to execute to find the `T` models linked to `Self`
///
/// # Example
///
/// ```rust
/// # use aragog::{Record, Validate, Link, DatabaseConnection, 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(not(feature = "blocking"))]
async fn linked_models<D>(&self, db_access: &D) -> Result<QueryResult<T>, Error>
where
Self: Sized,
D: DatabaseAccess + ?Sized,
T: 'async_trait,
{
DatabaseRecord::get(&self.link_query(), db_access).await
}
/// Retrieves the records matching the defined `link_query`. Type inference may be required.
#[cfg(feature = "blocking")]
fn linked_models<D>(&self, db_access: &D) -> Result<QueryResult<T>, Error>
where
D: DatabaseAccess + ?Sized,
{
DatabaseRecord::get(&self.link_query(), db_access)
}
}