[−][src]Trait domain_patterns::models::ValueObject
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.
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.