use super::char::validate_char_field;
use super::mixins::{FieldCacheMixin, FieldValidationMixin};
use crate::core::validators::validate_slug;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SlugField {
pub max_length: usize,
pub allow_unicode: bool,
pub db_index: bool,
}
impl Default for SlugField {
fn default() -> Self {
Self {
max_length: 50,
allow_unicode: false,
db_index: true,
}
}
}
impl SlugField {
#[must_use]
pub fn new(max_length: usize) -> Self {
Self {
max_length,
..Self::default()
}
}
#[must_use]
pub fn with_unicode(mut self) -> Self {
self.allow_unicode = true;
self
}
#[must_use]
pub fn max_length(&self) -> usize {
self.max_length
}
#[must_use]
pub fn db_type(&self) -> &str {
"VARCHAR"
}
}
impl FieldCacheMixin for SlugField {
fn get_cache_name(&self) -> String {
"slug_field".to_string()
}
fn is_cached(&self) -> bool {
self.db_index
}
}
impl FieldValidationMixin for SlugField {
fn validate(&self, value: &str) -> Result<(), String> {
validate_char_field(value, self.max_length).map_err(|error| error.message.clone())?;
if self.allow_unicode {
return Ok(());
}
validate_slug(value).map_err(|error| error.message)
}
}
#[cfg(test)]
mod tests {
use super::SlugField;
#[test]
fn slug_field_default_matches_django_defaults() {
let field = SlugField::default();
assert_eq!(field.max_length, 50);
assert!(!field.allow_unicode);
assert!(field.db_index);
}
#[test]
fn slug_field_new_overrides_max_length() {
let field = SlugField::new(128);
assert_eq!(field.max_length, 128);
assert!(field.db_index);
}
#[test]
fn slug_field_with_unicode_enables_unicode_support() {
let field = SlugField::default().with_unicode();
assert!(field.allow_unicode);
}
#[test]
fn slug_field_exposes_max_length() {
let field = SlugField::new(64);
assert_eq!(field.max_length(), 64);
}
#[test]
fn slug_field_reports_varchar_db_type() {
let field = SlugField::default();
assert_eq!(field.db_type(), "VARCHAR");
}
}