Skip to content

Commit

Permalink
feat: Add defaultValue to apply default values before constraints a…
Browse files Browse the repository at this point in the history
…re checked
  • Loading branch information
elpete committed Feb 7, 2025
1 parent 7a94b1b commit 3b5ba5a
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 5 deletions.
28 changes: 24 additions & 4 deletions models/GenericObject.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,34 @@ component {
* @missingMethodName
* @missingMethodArguments
*/
any function onMissingMethod( required string missingMethodName, required struct missingMethodArguments ){
var key = replaceNoCase( arguments.missingMethodName, "get", "" );

if ( structKeyExists( variables.collection, key ) ) {
any function onMissingMethod( required string missingMethodName, required any missingMethodArguments ){
if ( startsWith( arguments.missingMethodName, "set" ) ) {
var key = mid(
arguments.missingMethodName,
4,
len( arguments.missingMethodName ) - 3
);
variables.collection[ key ] = arguments.missingMethodArguments[ 1 ];
return variables.collection[ key ];
}

if ( startsWith( arguments.missingMethodName, "get" ) ) {
var key = mid(
arguments.missingMethodName,
4,
len( arguments.missingMethodName ) - 3
);
if ( structKeyExists( variables.collection, key ) ) {
return variables.collection[ key ];
}
}

// Return null
return javacast( "null", "" );
}

private boolean function startsWith( word, substring ){
return left( word, len( substring ) ) == substring;
}

}
55 changes: 54 additions & 1 deletion models/ValidationManager.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,27 @@ component accessors="true" serialize="false" singleton {
arguments.includeFields = arrayToList( arguments.includeFields );
}

// iterate over fields to apply default values
for ( var thisField in allConstraints ) {
/*
results = results,
rules = allConstraints[ thisField ],
target = arguments.target,
field = thisField,
locale = arguments.locale
*/
if ( allConstraints[ thisField ].keyExists( "defaultValue" ) ) {
var targetValue = invoke( arguments.target, "get" & thisField );
if ( isNull( targetValue ) || !hasValue( targetValue ) ) {
invoke(
arguments.target,
"set" & thisField,
[ allConstraints[ thisField ].defaultValue ]
);
}
}
}

// iterate over constraints defined
for ( var thisField in allConstraints ) {
var validateField = true;
Expand Down Expand Up @@ -304,7 +325,7 @@ component accessors="true" serialize="false" singleton {
// process the incoming rules
for ( var key in arguments.rules ) {
// if message validators, just ignore
if ( reFindNoCase( "Message$", key ) ) {
if ( reFindNoCase( "Message$", key ) || key == "defaultValue" ) {
continue;
}

Expand Down Expand Up @@ -507,4 +528,36 @@ component accessors="true" serialize="false" singleton {
);
}

/**
* Verify if the target value has a value
* Checks for nullness or for length if it's a simple value, array, query, struct or object.
*/
boolean function hasValue( any targetValue ){
// Null Tests
if ( isNull( arguments.targetValue ) ) {
return false;
}
// Simple Tests
if ( isSimpleValue( arguments.targetValue ) AND len( trim( arguments.targetValue ) ) ) {
return true;
}
// Array Tests
if ( isArray( arguments.targetValue ) and arrayLen( arguments.targetValue ) ) {
return true;
}
// Query Tests
if ( isQuery( arguments.targetValue ) and arguments.targetValue.recordcount ) {
return true;
}
// Struct Tests
if ( isStruct( arguments.targetValue ) and structCount( arguments.targetValue ) ) {
return true;
}
// Object
if ( isObject( arguments.targetValue ) ) {
return true;
}
return false;
}

}
11 changes: 11 additions & 0 deletions test-harness/tests/specs/ValidationManagerTest.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ component extends="coldbox.system.testing.BaseTestCase" appMapping="/root" {
debug( r.getAllErrors() );
} );

it( "can apply default values before validating", function(){
var mockData = { name : "luis" };
var mockConstraints = {
name : { required : true },
age : { required : true, max : 35, defaultValue : 30 }
};

var r = manager.validate( target = mockData, constraints = mockConstraints );
assertEquals( false, r.hasErrors() );
} );

it( "can validate with specific fields", function(){
var mockData = { name : "", age : "" };
var mockConstraints = {
Expand Down

0 comments on commit 3b5ba5a

Please sign in to comment.