[][src]Trait domain_patterns::models::ValueObject

pub trait ValueObject<T>: Clone + PartialEq + TryFrom<T> {
    type Error;
    fn validate(value: &T) -> bool;
fn value(&self) -> &T; }

A trait that defines a ValueObject which is an immutable holder of value, that validates that value against certain conditions before storing it.

Example

use std::{fmt, error};
use std::convert::TryFrom;
use regex::Regex;
use domain_patterns::models::ValueObject;


#[derive(Clone)]
struct Email {
    address: String,
}

impl PartialEq for Email {
    fn eq(&self, other: &Self) -> bool {
        self.address == other.address
    }
}

#[derive(Debug, Clone)]
struct EmailValidationError;

impl fmt::Display for EmailValidationError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Email failed to validate.")
    }
}

impl error::Error for EmailValidationError {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
}

impl TryFrom<String> for Email {
    type Error = EmailValidationError;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        if !Self::validate(&value) {
            return Err(EmailValidationError);
        }

        Ok(Email {
            address: value
        })
    }
}

impl ValueObject<String> for Email {
    type Error = EmailValidationError;

    fn validate(value: &String) -> bool {
        let email_rx = Regex::new(
            r"^(?i)[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$"
        ).unwrap();

        email_rx.is_match(value)
    }

    fn value(&self) -> &String {
        return &self.address;
    }
}

let email = Email::try_from("test_email@email.com".to_string()).unwrap();

Associated Types

type Error

The implementer of this trait must point this type at some sort of Error. This Error should communicate that there was some kind of validation error that occurred when trying to create the value object.

Loading content...

Required methods

fn validate(value: &T) -> bool

validate takes in incoming data used to construct the value object, and validates it against given constraints. An example would be if we had an Email struct that implements ValueObject. The constraints we would check would ensure that the incoming data is a valid email address.

Note: validate should be called by your implementation of try_from.

fn value(&self) -> &T

value return a reference to the internal value held in the value object. This should be the only way that we access the internal data. Mutation methods should always generate a new value object.

Loading content...

Implementors

Loading content...