mobx-decorated-models
Advanced tools
Comparing version 0.4.3 to 0.4.4
@@ -310,2 +310,5 @@ (function (global, factory) { | ||
if (!attrs || (typeof attrs === 'undefined' ? 'undefined' : _typeof(attrs)) !== 'object') { | ||
return attrs; | ||
} | ||
if (defaultAttributes) { | ||
@@ -355,3 +358,3 @@ if (typeof defaultAttributes === 'function') { | ||
if (change.type !== 'update') { | ||
if (change.type !== 'update' || !change.newValue) { | ||
return change; | ||
@@ -361,2 +364,3 @@ } | ||
for (var i = 0; i < array.length; i += 1) { | ||
@@ -368,4 +372,10 @@ array[i] = setupModel({ | ||
} | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
if (parentModel[parentModelProp]) { | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
} else { | ||
change.newValue = mobx.observable.array(array); | ||
return change; | ||
} | ||
} | ||
@@ -372,0 +382,0 @@ |
@@ -307,2 +307,5 @@ import { createModelSchema, deserialize, getDefaultModelSchema, identifier, list, object, primitive, serialize, update } from 'serializr'; | ||
if (!attrs || (typeof attrs === 'undefined' ? 'undefined' : _typeof(attrs)) !== 'object') { | ||
return attrs; | ||
} | ||
if (defaultAttributes) { | ||
@@ -352,3 +355,3 @@ if (typeof defaultAttributes === 'function') { | ||
if (change.type !== 'update') { | ||
if (change.type !== 'update' || !change.newValue) { | ||
return change; | ||
@@ -358,2 +361,3 @@ } | ||
for (var i = 0; i < array.length; i += 1) { | ||
@@ -365,4 +369,10 @@ array[i] = setupModel({ | ||
} | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
if (parentModel[parentModelProp]) { | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
} else { | ||
change.newValue = observable.array(array); | ||
return change; | ||
} | ||
} | ||
@@ -369,0 +379,0 @@ |
@@ -16,2 +16,5 @@ import { observable, intercept } from 'mobx'; | ||
}) { | ||
if (!attrs || typeof attrs !== 'object') { | ||
return attrs; | ||
} | ||
if (defaultAttributes) { | ||
@@ -53,4 +56,5 @@ if (typeof defaultAttributes === 'function') { | ||
parentModel, parentModelProp }) { | ||
if (change.type !== 'update') { return change; } | ||
if (change.type !== 'update' || !change.newValue) { return change; } | ||
const { newValue: array } = change; | ||
for (let i = 0; i < array.length; i += 1) { | ||
@@ -62,4 +66,10 @@ array[i] = setupModel({ | ||
} | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
if (parentModel[parentModelProp]) { | ||
parentModel[parentModelProp].replace(array); | ||
return null; | ||
} else { | ||
change.newValue = observable.array(array); | ||
return change; | ||
} | ||
} | ||
@@ -66,0 +76,0 @@ |
{ | ||
"name": "mobx-decorated-models", | ||
"version": "0.4.3", | ||
"version": "0.4.4", | ||
"description": "Decorators to make using Mobx for model type structures easier", | ||
@@ -5,0 +5,0 @@ "main": "dist/build.full.js", |
@@ -83,40 +83,6 @@ # Decorators for creating model type structures with mobx | ||
class Table { | ||
hasMany({ classId: 'chair' }) 'seats' | ||
hasMany({ model: 'chair' }) 'seats' | ||
} | ||
``` | ||
This works well enough, however using the `name` property is fragile, since it relies on the class name | ||
not changing. Certain JS minimizers may rename classes. | ||
If custom logic is needed, it's possible to supply custom "record" and "lookup" functions. | ||
*Example* that uses a static `identifiedBy` property. | ||
```javascript | ||
import { model, lookupModelUsing, rememberModelUsing } from 'mobx-decorated-models'; | ||
import { capitalize, singularize } from 'utility'; | ||
const Models = {}; | ||
lookupModelUsing((propertyName, propertyOptions) => { | ||
return Models[propertyOptions.classId] || | ||
Models[capitalize(propertyName)] || | ||
Models[capitalize(singularize(propertyName))]; | ||
}); | ||
rememberModelUsing(klass => Models[klass.identifiedBy] = klass); | ||
@modelDecorator | ||
class ATestingModel { | ||
static identifiedBy = 'test'; | ||
belongsTo document; | ||
} | ||
@modelDecorator | ||
class Document { | ||
static identifiedBy = 'document'; | ||
hasMany({ classId: 'test' }) testRuns; | ||
} | ||
``` | ||
### Decorators | ||
@@ -169,4 +135,5 @@ | ||
Optionally can be given an option object with a `classId` property to control the mapping. | ||
Optionally can be given an option object with a `model` property to control the mapping. | ||
`model` can be either a string which matches a value given to the modelDecorator, or a reference to the model itself. | ||
@@ -180,9 +147,13 @@ *example:* | ||
@field name; | ||
@belongsTo({ classId: 'Pants', inverseOf: 'owner' }) outfit; | ||
// finds a model that was set to use the id `pants` by it's decorator | ||
@belongsTo({ model: 'pants', inverseOf: 'owner' }) outfit; | ||
speak(msg) { | ||
console.log(`${this.name} says: ${msg}`); | ||
} | ||
}) | ||
@modelDecorator | ||
@modelDecorator('pants') | ||
class Pants { | ||
@session color; | ||
@belongsTo({ classId: 'Person' }) owner; // looks for class `Person` | ||
@belongsTo({ model: Person }) owner; // no lookup, will just use the class `Person` | ||
} | ||
@@ -201,2 +172,12 @@ ``` | ||
An interceptor is installed that will convert bare objects to a model. In the example below, the owner will be set to an instance of Person | ||
```javascript | ||
const pants = new Pants(); | ||
pants.owner = { id: 1, name: 'Jimmy' }; | ||
pants.owner.speak("Hello World!"); // Jimmy says: Hello World | ||
``` | ||
**Note**: When using `inverseOf`, the auto-set property is not serialized in order to prevent circular references. | ||
@@ -210,3 +191,3 @@ | ||
As in `belongsTo`, can be optionally given an option object with a `classId` property to control the mapping. | ||
As in `belongsTo`, can be optionally given an option object with a `model` property to control the mapping. | ||
@@ -219,2 +200,3 @@ `hasMany` also accepts `inverseOf` and `defaults` properties. If an inverseOf is provided, | ||
Like `belongsTo`, `hasMany` also converts object assignment to a model | ||
@@ -232,3 +214,3 @@ ```javascript | ||
@session color; | ||
@hasMany({ classId: 'Tire', inverseOf: 'vehicle', defaults: {numberInSet: 4} }) tires; | ||
@hasMany({ model: 'Tire', inverseOf: 'vehicle', defaults: {numberInSet: 4} }) tires; | ||
} | ||
@@ -240,3 +222,3 @@ | ||
@hasMany({ | ||
classId: 'Car', | ||
model: 'Car', | ||
inverseOf: 'home', | ||
@@ -243,0 +225,0 @@ defaults(collection, parent) { |
@@ -115,2 +115,19 @@ import { autorun } from 'mobx'; | ||
it('passes on values that can’t be handled', () => { | ||
const ship = Ship.deserialize({ name: 'HMS Glory' }); | ||
expect(ship.box).toBeUndefined(); | ||
ship.box = undefined; | ||
expect(ship.box).toBeUndefined(); | ||
ship.box = 1; | ||
expect(ship.box).toBe(1); | ||
const container = new Container(); | ||
container.boxes = [{ id: 1 }]; | ||
expect(container.boxes[0]).toBeInstanceOf(Box); | ||
container.boxes = undefined; | ||
expect(container.boxes).toBeUndefined(); | ||
container.boxes = [{ id: 1 }, null]; | ||
expect(container.boxes[0].id).toBe(1); | ||
expect(container.boxes[1]).toBeNull(); | ||
}); | ||
it('guards against setting a hasMany', () => { | ||
@@ -117,0 +134,0 @@ const container = Container.deserialize({ id: 1 }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
210294
1548
255