Skip to content

Commit 1c06e64

Browse files
Merge pull request #21 from scup/dynamic-type-builder
types can be build using builder
2 parents 53531bc + f3e753c commit 1c06e64

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,36 @@ console.log(fatherInstance.children[0]); //An instance of MyEntity
9090
console.log(fatherInstance.children[1].toJSON());
9191
//{ field: 'B', otherField: 3 }
9292
```
93-
93+
#### Builder
94+
When you need to create objects with custom verification like
95+
```javascript
96+
const elementList = {
97+
elements: [{
98+
type: 'product',
99+
name: true,
100+
price: true
101+
}, {
102+
type: 'default',
103+
isDefault: true
104+
}]
105+
};
106+
```
107+
In such cases you can define a builder as follows:
108+
```javascript
109+
class ElementList extends Speck {}
110+
ElementList.SCHEMA = {
111+
elements: {
112+
validator: noop,
113+
builder: (dataList) => dataList.map(data => {
114+
if (data.type === 'product') return new ProductEntity(data);
115+
if (data.type === 'default') return new FakeEntityWithBoolean(data);
116+
})
117+
}
118+
};
119+
```
120+
By defining builder you tell Speck Entity that you take the responsibility of instansitating and
121+
returning a new object of the type which suits you the best.
122+
This is a powerful concept as it lets users dynamically create new types on the fly.
94123
#### Clean unexpected values
95124
```javascript
96125
const anotherInstance = new MyEntity({ field: 'myString', fake: 'fake' });

spec/Speck.spec.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import {
1616
FatherWithObjectEntity,
1717
FakeEntityWithExcludeContext,
1818
FakeEntityWithIncludeContext,
19-
FakeEntityWithCustomValidationWithContext
19+
FakeEntityWithCustomValidationWithContext,
20+
FakeEntityWithCustomElementList
2021
} from './fixtures/fakerClasses';
2122

2223
describe('Speck', () => {
@@ -125,6 +126,22 @@ describe('Speck', () => {
125126
});
126127

127128
describe('children', () => {
129+
it('builds Hetrogenerous types in a list automatically', () => {
130+
const elementEntity = new FakeEntityWithCustomElementList({
131+
elements: [{
132+
type: 'product',
133+
name: true,
134+
price: true
135+
}, {
136+
type: 'default',
137+
isDefault: true
138+
}]
139+
});
140+
141+
expect(elementEntity.elements[0].constructor).to.equal(ProductEntity);
142+
expect(elementEntity.elements[1].constructor).to.equal(FakeEntityWithBoolean);
143+
});
144+
128145
it('builds automatically child entities of array', () => {
129146
const father = new FatherEntity({
130147
children: [

spec/fixtures/fakerClasses.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ function alwaysTruth(){
2424
return true;
2525
}
2626

27+
class FakeEntityWithCustomElementList extends Speck {}
28+
FakeEntityWithCustomElementList.SCHEMA = {
29+
elements: {
30+
validator: noop,
31+
builder: (dataList) => dataList.map(data => {
32+
if (data.type === 'product') return new ProductEntity(data);
33+
if (data.type === 'default') return new FakeEntityWithBoolean(data);
34+
})
35+
}
36+
};
37+
2738
class ProductEntity extends Speck { }
2839
ProductEntity.SCHEMA = {
2940
name: alwaysTruth,
@@ -153,5 +164,6 @@ Object.assign(exports, {
153164
FatherWithObjectEntity,
154165
FakeEntityWithExcludeContext,
155166
FakeEntityWithIncludeContext,
156-
FakeEntityWithCustomValidationWithContext
167+
FakeEntityWithCustomValidationWithContext,
168+
FakeEntityWithCustomElementList
157169
});

src/Speck.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { get, isNil } from 'lodash';
1+
import { get, isNil, isFunction } from 'lodash';
22

33
const createGetterAndSetter = function (instance, field){
44
return {
@@ -46,7 +46,7 @@ class Speck {
4646

4747
newData[field] = isNil(data[field]) ? this.schema[field].defaultValue: data[field];
4848

49-
if (this.schema[field].type) {
49+
if (this.schema[field].type || this.schema[field].builder) {
5050
newData[field] = this.applyEntityConstructor(this.schema[field], newData[field]);
5151
}
5252

@@ -111,7 +111,7 @@ class Speck {
111111
applyEntityConstructor(field, data) {
112112
const Type = field.type;
113113

114-
if(field.builder) {
114+
if(isFunction(field.builder)) {
115115
return field.builder(data, Type);
116116
}
117117

0 commit comments

Comments
 (0)