use rustrails_support::inflector::{foreign_key, tableize};
use super::{AssociationMeta, AssociationType};
#[derive(Debug, Clone)]
pub struct BelongsToBuilder {
name: String,
foreign_key: Option<String>,
primary_key: Option<String>,
polymorphic: bool,
}
impl BelongsToBuilder {
#[must_use]
pub fn new(name: &str) -> Self {
Self {
name: name.to_owned(),
foreign_key: None,
primary_key: None,
polymorphic: false,
}
}
#[must_use]
pub fn foreign_key(mut self, fk: &str) -> Self {
self.foreign_key = Some(fk.to_owned());
self
}
#[must_use]
pub fn primary_key(mut self, key: &str) -> Self {
self.primary_key = Some(key.to_owned());
self
}
#[must_use]
pub fn polymorphic(mut self) -> Self {
self.polymorphic = true;
self
}
#[must_use]
pub fn build(self) -> AssociationMeta {
let name = self.name;
let inferred_key = foreign_key(&name);
AssociationMeta {
target_table: tableize(&name),
foreign_key: self.foreign_key.unwrap_or(inferred_key),
primary_key: self.primary_key.unwrap_or_else(|| "id".to_owned()),
dependent: None,
through: None,
polymorphic: self.polymorphic,
association_type: AssociationType::BelongsTo,
name,
}
}
}
#[cfg(test)]
mod tests {
use super::BelongsToBuilder;
use crate::associations::AssociationType;
#[test]
fn build_defaults_foreign_key_from_association_name() {
let meta = BelongsToBuilder::new("author").build();
assert_eq!(meta.association_type, AssociationType::BelongsTo);
assert_eq!(meta.target_table, "authors");
assert_eq!(meta.foreign_key, "author_id");
assert_eq!(meta.primary_key, "id");
assert!(!meta.polymorphic);
}
#[test]
fn build_supports_custom_keys() {
let meta = BelongsToBuilder::new("account")
.foreign_key("owner_uuid")
.primary_key("uuid")
.build();
assert_eq!(meta.foreign_key, "owner_uuid");
assert_eq!(meta.primary_key, "uuid");
}
#[test]
fn build_marks_polymorphic_associations() {
let meta = BelongsToBuilder::new("attachable").polymorphic().build();
assert!(meta.polymorphic);
}
#[test]
fn build_preserves_association_name() {
let meta = BelongsToBuilder::new("author").build();
assert_eq!(meta.name, "author");
}
#[test]
fn foreign_key_override_keeps_default_primary_key() {
let meta = BelongsToBuilder::new("author")
.foreign_key("writer_id")
.build();
assert_eq!(meta.foreign_key, "writer_id");
assert_eq!(meta.primary_key, "id");
}
#[test]
fn primary_key_override_keeps_inferred_foreign_key() {
let meta = BelongsToBuilder::new("author").primary_key("uuid").build();
assert_eq!(meta.foreign_key, "author_id");
assert_eq!(meta.primary_key, "uuid");
}
#[test]
fn polymorphic_preserves_default_keys() {
let meta = BelongsToBuilder::new("attachable").polymorphic().build();
assert_eq!(meta.foreign_key, "attachable_id");
assert_eq!(meta.primary_key, "id");
}
#[test]
fn build_does_not_set_dependent_or_through_metadata() {
let meta = BelongsToBuilder::new("author").build();
assert!(meta.dependent.is_none());
assert!(meta.through.is_none());
}
}