Skip to content

Commit

Permalink
Fix #413: allow nested defaults on objects.
Browse files Browse the repository at this point in the history
  • Loading branch information
Marsup committed Apr 13, 2015
1 parent 4776480 commit 03d190f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 3 deletions.
1 change: 1 addition & 0 deletions .eslintignore
@@ -1 +1,2 @@
examples
sandbox.js
7 changes: 5 additions & 2 deletions README.md
Expand Up @@ -437,10 +437,13 @@ Strict mode sets the `options.convert` options to `false` which prevent type cas
var schema = Joi.any().strict();
```

#### `any.default(value, [description])`
#### `any.default([value, [description]])`

Sets a default value if the original value is undefined where:
- `value` - the value. `value` supports [references](#refkey-options). `value` may also be a function which returns the default value. If `value` is specified as a function that accepts a single parameter, that parameter will be a context object that can be used to derive the resulting value. **This clones the object however, which incurs some overhead so if you don't need access to the context define your method so that it does not accept any parameters**.
- `value` - the value.
- `value` supports [references](#refkey-options).
- `value` may also be a function which returns the default value. If `value` is specified as a function that accepts a single parameter, that parameter will be a context object that can be used to derive the resulting value. **This clones the object however, which incurs some overhead so if you don't need access to the context define your method so that it does not accept any parameters**.
- without any `value`, `default` has no effect, except for `object` that will then create nested defaults (applying inner defaults of that object).

Note that if `value` is an object, any changes to the object after `default()` is called will change the reference
and any future assignment.
Expand Down
8 changes: 7 additions & 1 deletion lib/any.js
Expand Up @@ -500,7 +500,13 @@ internals.Any.prototype._validate = function (value, state, options, reference)
var presence = this._flags.presence || options.presence;
if (presence === 'optional') {
if (value === undefined) {
return finish();
var isDeepDefault = this._flags.hasOwnProperty('default') && this._flags.default === undefined;
if (isDeepDefault && this._type === 'object') {
value = {};
}
else {
return finish();
}
}
}
else if (presence === 'required' &&
Expand Down
28 changes: 28 additions & 0 deletions test/any.js
Expand Up @@ -506,6 +506,34 @@ describe('any', function () {
done();
});
});

it('creates deep defaults', function (done) {

var schema = Joi.object({
a: Joi.number().default(42),
b: Joi.object({
c: Joi.boolean().default(true),
d: Joi.string()
}).default()
}).default();

Helper.validate(schema, [
[undefined, true, null, { a: 42, b: { c: true }}],
[{ a: 24 }, true, null, { a: 24, b: { c: true }}]
], done);
});

it('should not affect objects other than object when called without an argument', function (done) {

var schema = Joi.object({
a: Joi.number().default()
}).default();

Helper.validate(schema, [
[undefined, true, null, {}],
[{ a: 24 }, true, null, { a: 24 }]
], done);
});
});

describe('#optional', function () {
Expand Down

0 comments on commit 03d190f

Please sign in to comment.