fix #429 Multiple Models can't mixin same class
Signed-off-by: Clark Wang <clark.wangs@gmail.com>
This commit is contained in:
parent
159be756ac
commit
90e169c1a6
12
lib/jutil.js
12
lib/jutil.js
|
@ -1,4 +1,5 @@
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
|
var _ = require('lodash');
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param newClass
|
* @param newClass
|
||||||
|
@ -61,7 +62,7 @@ exports.mixin = function (newClass, mixinClass, options) {
|
||||||
if (options.instanceProperties && mixinClass.prototype) {
|
if (options.instanceProperties && mixinClass.prototype) {
|
||||||
mixInto(mixinClass.prototype, newClass.prototype, options);
|
mixInto(mixinClass.prototype, newClass.prototype, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newClass;
|
return newClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,11 +76,12 @@ function mixInto(sourceScope, targetScope, options) {
|
||||||
var isDelegate = isFunc && targetProperty.value._delegate;
|
var isDelegate = isFunc && targetProperty.value._delegate;
|
||||||
var shouldOverride = options.override || !targetPropertyExists || isDelegate;
|
var shouldOverride = options.override || !targetPropertyExists || isDelegate;
|
||||||
|
|
||||||
|
if (propertyName == '_mixins') {
|
||||||
|
targetScope._mixins = _.union(targetScope._mixins, sourceScope._mixins);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldOverride) {
|
if (shouldOverride) {
|
||||||
if (sourceIsFunc) {
|
|
||||||
sourceProperty.value = sourceProperty.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperty(targetScope, propertyName, sourceProperty);
|
Object.defineProperty(targetScope, propertyName, sourceProperty);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,7 +41,7 @@ function timestamps(Model, options) {
|
||||||
mixins.define('TimeStamp', timestamps);
|
mixins.define('TimeStamp', timestamps);
|
||||||
|
|
||||||
describe('Model class', function () {
|
describe('Model class', function () {
|
||||||
|
|
||||||
it('should define mixins', function() {
|
it('should define mixins', function() {
|
||||||
mixins.define('Example', function(Model, options) {
|
mixins.define('Example', function(Model, options) {
|
||||||
Model.prototype.example = function() {
|
Model.prototype.example = function() {
|
||||||
|
@ -56,7 +56,7 @@ describe('Model class', function () {
|
||||||
Model.multiMixin[options.key] = options.value;
|
Model.multiMixin[options.key] = options.value;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply a mixin class', function() {
|
it('should apply a mixin class', function() {
|
||||||
var Address = modelBuilder.define('Address', {
|
var Address = modelBuilder.define('Address', {
|
||||||
street: { type: 'string', required: true },
|
street: { type: 'string', required: true },
|
||||||
|
@ -69,34 +69,34 @@ describe('Model class', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
var properties = Item.definition.properties;
|
var properties = Item.definition.properties;
|
||||||
|
|
||||||
properties.street.should.eql({ type: String, required: true });
|
properties.street.should.eql({ type: String, required: true });
|
||||||
properties.city.should.eql({ type: String, required: true });
|
properties.city.should.eql({ type: String, required: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply mixins', function(done) {
|
it('should apply mixins', function(done) {
|
||||||
var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
|
var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
|
||||||
var Item = memory.createModel('Item', { name: 'string' }, {
|
var Item = memory.createModel('Item', { name: 'string' }, {
|
||||||
mixins: {
|
mixins: {
|
||||||
TimeStamp: true, Demo: { value: true },
|
TimeStamp: true, Demo: { value: true },
|
||||||
Multi: [
|
Multi: [
|
||||||
{ key: 'foo', value: 'bar' },
|
{ key: 'foo', value: 'bar' },
|
||||||
{ key: 'fox', value: 'baz' }
|
{ key: 'fox', value: 'baz' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Item.mixin('Example', { foo: 'bar' });
|
Item.mixin('Example', { foo: 'bar' });
|
||||||
|
|
||||||
Item.demoMixin.should.be.true;
|
Item.demoMixin.should.be.true;
|
||||||
|
|
||||||
Item.multiMixin.foo.should.equal('bar');
|
Item.multiMixin.foo.should.equal('bar');
|
||||||
Item.multiMixin.fox.should.equal('baz');
|
Item.multiMixin.fox.should.equal('baz');
|
||||||
|
|
||||||
var properties = Item.definition.properties;
|
var properties = Item.definition.properties;
|
||||||
properties.createdAt.should.eql({ type: Date });
|
properties.createdAt.should.eql({ type: Date });
|
||||||
properties.updatedAt.should.eql({ type: Date });
|
properties.updatedAt.should.eql({ type: Date });
|
||||||
|
|
||||||
Item.create({ name: 'Item 1' }, function(err, inst) {
|
Item.create({ name: 'Item 1' }, function(err, inst) {
|
||||||
inst.createdAt.should.be.a.date;
|
inst.createdAt.should.be.a.date;
|
||||||
inst.updatedAt.should.be.a.date;
|
inst.updatedAt.should.be.a.date;
|
||||||
|
@ -104,5 +104,37 @@ describe('Model class', function () {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#mixin()', function () {
|
||||||
|
|
||||||
|
var Person, Author, Address;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
Address = modelBuilder.define('Address', {
|
||||||
|
street: { type: 'string', required: true },
|
||||||
|
city: { type: 'string', required: true }
|
||||||
|
});
|
||||||
|
var memory = new DataSource('mem', {connector: Memory}, modelBuilder);
|
||||||
|
Person = memory.createModel('Person', { name: 'string' });
|
||||||
|
Author = memory.createModel('Author', { name: 'string' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should register mixin class into _mixins', function () {
|
||||||
|
Person.mixin(Address);
|
||||||
|
Person._mixins.should.containEql(Address);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT share mixins registry', function () {
|
||||||
|
Person.mixin(Address);
|
||||||
|
Author._mixins.should.not.containEql(Address);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should able to mixin same class', function () {
|
||||||
|
Person.mixin(Address);
|
||||||
|
Author.mixin(Address);
|
||||||
|
Author._mixins.should.containEql(Address);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue