Skip to content

Commit 9514c18

Browse files
Merge pull request #36 from vicentelyrio/constructor-with-deps
Passing deps to builder
2 parents 2103fde + 842ad05 commit 9514c18

File tree

7 files changed

+714
-16
lines changed

7 files changed

+714
-16
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ console.log(fatherInstance.children[1].toJSON());
9292
//{ field: 'B', otherField: 3 }
9393
```
9494
#### Builder
95-
When you need to create objects with custom verification like
95+
When you need to create objects with custom verification like
9696
```javascript
9797
const elementList = {
9898
elements: [{
@@ -111,15 +111,21 @@ class ElementList extends Speck {}
111111
ElementList.SCHEMA = {
112112
elements: {
113113
validator: noop,
114-
builder: (dataList) => dataList.map(data => {
115-
if (data.type === 'product') return new ProductEntity(data);
114+
builder: (dataList, Type, dependencies) => dataList.map(data => {
115+
if (data.type === 'product') return new ProductEntity(data, dependencies);
116116
if (data.type === 'default') return new FakeEntityWithBoolean(data);
117117
})
118118
}
119119
};
120120
```
121-
By defining builder you tell Speck Entity that you take the responsibility of instansitating and
122-
returning a new object of the type which suits you the best.
121+
And use it like:
122+
```javascript
123+
new ElementList(elementList, someDependency)
124+
```
125+
(note that you can pass custom dependencies to your child entities and latter access them on the builder)
126+
127+
By defining builder you tell Speck Entity that you take the responsibility of instansitating and
128+
returning a new object of the type which suits you the best.
123129
This is a powerful concept as it lets users dynamically create new types on the fly.
124130
#### Clean unexpected values
125131
```javascript
@@ -230,4 +236,4 @@ To understand the validators [React PropTypes](https://facebook.github.io/react/
230236
const myEntity = new EntityWithHook({ fieldWithHook: 'foo', anotherFieldWithHook: 'bar', anotherField: null });
231237

232238
myEntity.anotherFieldWithHook = 10 //according to the after set hook anotherField newValue will be 20
233-
```
239+
```

lib/Speck.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ var Speck = function () {
6767
enumerable: false
6868
});
6969

70+
for (var _len = arguments.length, dependencies = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
71+
dependencies[_key - 1] = arguments[_key];
72+
}
73+
7074
Object.defineProperty(this, 'data', {
71-
value: this._mergeDefault(data),
75+
value: this._mergeDefault.apply(this, [data].concat(dependencies)),
7276
enumerable: false
7377
});
7478

@@ -97,11 +101,16 @@ var Speck = function () {
97101
value: function _mergeDefault(data) {
98102
var newData = {};
99103
var field = void 0;
104+
105+
for (var _len2 = arguments.length, dependencies = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
106+
dependencies[_key2 - 1] = arguments[_key2];
107+
}
108+
100109
for (field in this.schema) {
101110
newData[field] = this.__initFieldValue(field, data);
102111

103112
if (this.schema[field].type || this.schema[field].builder) {
104-
newData[field] = this.applyEntityConstructor(this.schema[field], newData[field]);
113+
newData[field] = this.applyEntityConstructor.apply(this, [this.schema[field], newData[field]].concat(dependencies));
105114
}
106115

107116
Object.defineProperty(this, field, createGetterAndSetter(this, field));
@@ -171,7 +180,11 @@ var Speck = function () {
171180
var Type = field.type;
172181

173182
if (isFunction(field.builder)) {
174-
return field.builder(data, Type);
183+
for (var _len3 = arguments.length, dependencies = Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
184+
dependencies[_key3 - 2] = arguments[_key3];
185+
}
186+
187+
return field.builder.apply(field, [data, Type].concat(dependencies));
175188
}
176189

177190
if (!data) return;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "speck-entity",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "Domain entities with reactive validation",
55
"main": "lib/index.js",
66
"scripts": {

spec/Speck.spec.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ const {
1111
ProductEntity,
1212
Validatable,
1313
ChildrenEntity,
14+
ChildrenWithDependency,
1415
FatherEntity,
1516
FatherWithObjectEntity,
17+
FatherWithDependencies,
1618
FakeEntityWithExcludeContext,
1719
FakeEntityWithIncludeContext,
1820
FakeEntityWithCustomValidationWithContext,
@@ -172,6 +174,17 @@ describe('Speck', () => {
172174
expect(father.children.tweet.constructor).to.equal(ChildrenEntity)
173175
})
174176

177+
it('builds automatically using the parameter builder and passing dependencies', () => {
178+
const father = new FatherWithDependencies({
179+
children: { foo: 'bar' }
180+
}, {
181+
dependency: true
182+
})
183+
184+
expect(father.children.constructor).to.equal(ChildrenWithDependency)
185+
expect(father.children.dependency).to.equal(true)
186+
})
187+
175188
it('includes errors of children', () => {
176189
const father = new FatherEntity({
177190
foo: 'test',

spec/fixtures/fakerClasses.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ ChildrenEntity.SCHEMA = {
7373
foo: fooValidator
7474
}
7575

76+
class ChildrenWithDependency extends Speck {
77+
constructor (props, dependencies) {
78+
super(props, dependencies)
79+
80+
Object.assign(this, dependencies)
81+
}
82+
}
83+
ChildrenWithDependency.SCHEMA = {
84+
foo: fooValidator
85+
}
86+
7687
FakeEntityWithDefault.SCHEMA = {
7788
[defaultField]: {
7889
validator: noop,
@@ -126,6 +137,17 @@ FatherWithObjectEntity.SCHEMA = {
126137
}
127138
}
128139

140+
class FatherWithDependencies extends Speck { }
141+
FatherWithDependencies.SCHEMA = {
142+
children: {
143+
type: ChildrenWithDependency,
144+
validator: alwaysTruth,
145+
builder: (data, Type, dependencies) => {
146+
return new Type(data, dependencies)
147+
}
148+
}
149+
}
150+
129151
class FakeEntityWithExcludeContext extends Speck { }
130152
FakeEntityWithExcludeContext.SCHEMA = {
131153
id: joiAdapter(Joi.number().required()),
@@ -176,8 +198,10 @@ Object.assign(exports, {
176198
ProductEntity,
177199
Validatable,
178200
ChildrenEntity,
201+
ChildrenWithDependency,
179202
FatherEntity,
180203
FatherWithObjectEntity,
204+
FatherWithDependencies,
181205
FakeEntityWithExcludeContext,
182206
FakeEntityWithIncludeContext,
183207
FakeEntityWithCustomValidationWithContext,

src/Speck.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function createGetterAndSetter (instance, field) {
2727
}
2828

2929
class Speck {
30-
constructor (data = {}) {
30+
constructor (data = {}, ...dependencies) {
3131
Object.defineProperty(this, 'schema', {
3232
value: this.constructor.SCHEMA,
3333
enumerable: false
@@ -44,7 +44,7 @@ class Speck {
4444
})
4545

4646
Object.defineProperty(this, 'data', {
47-
value: this._mergeDefault(data),
47+
value: this._mergeDefault(data, ...dependencies),
4848
enumerable: false
4949
})
5050

@@ -66,14 +66,14 @@ class Speck {
6666
return isFunction ? defaultValue : clone(this.schema[field].defaultValue)
6767
}
6868

69-
_mergeDefault (data) {
69+
_mergeDefault (data, ...dependencies) {
7070
const newData = {}
7171
let field
7272
for (field in this.schema) {
7373
newData[field] = this.__initFieldValue(field, data)
7474

7575
if (this.schema[field].type || this.schema[field].builder) {
76-
newData[field] = this.applyEntityConstructor(this.schema[field], newData[field])
76+
newData[field] = this.applyEntityConstructor(this.schema[field], newData[field], ...dependencies)
7777
}
7878

7979
Object.defineProperty(this, field, createGetterAndSetter(this, field))
@@ -132,11 +132,11 @@ class Speck {
132132
return children.reduce(this._includeChildErrors.bind(this, field), errors)
133133
}
134134

135-
applyEntityConstructor (field, data) {
135+
applyEntityConstructor (field, data, ...dependencies) {
136136
const Type = field.type
137137

138138
if (isFunction(field.builder)) {
139-
return field.builder(data, Type)
139+
return field.builder(data, Type, ...dependencies)
140140
}
141141

142142
if (!data) return

0 commit comments

Comments
 (0)