use std::marker::PhantomData;
use super::reverse::ReverseRelationship;
#[derive(Debug, Clone)]
pub struct OneToMany<T, K> {
pub accessor_name: String,
pub foreign_key_field: String,
pub to_field: String,
pub lazy: bool,
_phantom_t: PhantomData<T>,
_phantom_k: PhantomData<K>,
}
impl<T, K> OneToMany<T, K> {
pub fn new(accessor_name: impl Into<String>) -> Self {
Self {
accessor_name: accessor_name.into(),
foreign_key_field: String::new(),
to_field: "id".to_string(),
lazy: true,
_phantom_t: PhantomData,
_phantom_k: PhantomData,
}
}
pub fn foreign_key(mut self, field_name: impl Into<String>) -> Self {
self.foreign_key_field = field_name.into();
self
}
pub fn to_field(mut self, to_field: impl Into<String>) -> Self {
self.to_field = to_field.into();
self
}
pub fn lazy(mut self, lazy: bool) -> Self {
self.lazy = lazy;
self
}
pub fn accessor_name(&self) -> &str {
&self.accessor_name
}
pub fn foreign_key_field(&self) -> &str {
&self.foreign_key_field
}
pub fn get_to_field(&self) -> &str {
&self.to_field
}
pub fn is_lazy(&self) -> bool {
self.lazy
}
}
impl<T, K> Default for OneToMany<T, K> {
fn default() -> Self {
Self::new("items")
}
}
impl<T, K> ReverseRelationship for OneToMany<T, K> {
fn get_or_generate_reverse_name(&self, _model_name: &str) -> String {
self.accessor_name.clone()
}
fn explicit_reverse_name(&self) -> Option<&str> {
Some(&self.accessor_name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(dead_code)]
#[derive(Clone)]
struct User {
id: i64,
name: String,
}
#[allow(dead_code)]
#[derive(Clone)]
struct Post {
id: i64,
author_id: i64,
title: String,
}
#[test]
fn test_one_to_many_creation() {
let rel: OneToMany<Post, i64> = OneToMany::new("posts");
assert_eq!(rel.accessor_name(), "posts");
assert_eq!(rel.foreign_key_field(), "");
assert_eq!(rel.get_to_field(), "id");
assert!(rel.is_lazy());
}
#[test]
fn test_one_to_many_builder() {
let rel: OneToMany<Post, i64> = OneToMany::new("posts")
.foreign_key("author_id")
.to_field("uuid")
.lazy(false);
assert_eq!(rel.accessor_name(), "posts");
assert_eq!(rel.foreign_key_field(), "author_id");
assert_eq!(rel.get_to_field(), "uuid");
assert!(!rel.is_lazy());
}
#[test]
fn test_foreign_key_field() {
let rel: OneToMany<Post, i64> = OneToMany::new("posts").foreign_key("user_id");
assert_eq!(rel.foreign_key_field(), "user_id");
}
#[test]
fn test_to_field_customization() {
let rel: OneToMany<Post, i64> = OneToMany::new("posts").to_field("user_uuid");
assert_eq!(rel.get_to_field(), "user_uuid");
}
#[test]
fn test_lazy_loading_configuration() {
let rel1: OneToMany<Post, i64> = OneToMany::new("posts").lazy(true);
assert!(rel1.is_lazy());
let rel2: OneToMany<Post, i64> = OneToMany::new("posts").lazy(false);
assert!(!rel2.is_lazy());
}
#[test]
fn test_default_values() {
let rel: OneToMany<Post, i64> = OneToMany::new("comments");
assert_eq!(rel.accessor_name(), "comments");
assert!(rel.is_lazy());
assert_eq!(rel.get_to_field(), "id");
}
#[test]
fn test_multiple_relationships() {
let posts: OneToMany<Post, i64> = OneToMany::new("posts").foreign_key("author_id");
let comments: OneToMany<Post, i64> = OneToMany::new("comments").foreign_key("user_id");
assert_eq!(posts.accessor_name(), "posts");
assert_eq!(posts.foreign_key_field(), "author_id");
assert_eq!(comments.accessor_name(), "comments");
assert_eq!(comments.foreign_key_field(), "user_id");
}
}