Skip to content

Commit d8ae4a9

Browse files
committed
fix: update .labels() fn to support subschemas
fixes #400
1 parent 555b262 commit d8ae4a9

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

package/lib/SimpleSchema.js

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,42 @@ class SimpleSchema {
146146
});
147147
}
148148

149+
/**
150+
* @param {String} key One specific or generic key for which to get the schema.
151+
* @returns {[SimpleSchema, String]} Returns a 2-tuple.
152+
*
153+
* First item: The SimpleSchema instance that actually defines the given key.
154+
*
155+
* For example, if you have several nested objects, each their own SimpleSchema
156+
* instance, and you pass in 'outerObj.innerObj.innerestObj.name' as the key, you'll
157+
* get back the SimpleSchema instance for `outerObj.innerObj.innerestObj` key.
158+
*
159+
* But if you pass in 'outerObj.innerObj.innerestObj.name' as the key and that key is
160+
* defined in the main schema without use of subschemas, then you'll get back the main schema.
161+
*
162+
* Second item: The part of the key that is in the found schema.
163+
*
164+
* Always returns a tuple (array) but the values may be `null`.
165+
*/
166+
nearestSimpleSchemaInstance(key) {
167+
if (!key) return [null, null];
168+
169+
const genericKey = MongoObject.makeKeyGeneric(key);
170+
if (this._schema[genericKey]) return [this, genericKey];
171+
172+
// If not defined in this schema, see if it's defined in a subschema
173+
let innerKey;
174+
let nearestSimpleSchemaInstance;
175+
this.forEachAncestorSimpleSchema(key, (simpleSchema, ancestor, subSchemaKey) => {
176+
if (!nearestSimpleSchemaInstance && simpleSchema._schema[subSchemaKey]) {
177+
nearestSimpleSchemaInstance = simpleSchema;
178+
innerKey = subSchemaKey;
179+
}
180+
});
181+
182+
return innerKey ? [nearestSimpleSchemaInstance, innerKey] : [null, null];
183+
}
184+
149185
/**
150186
* @param {String} [key] One specific or generic key for which to get the schema.
151187
* @returns {Object} The entire schema object or just the definition for one key.
@@ -702,10 +738,12 @@ class SimpleSchema {
702738
Object.keys(labels).forEach((key) => {
703739
const label = labels[key];
704740
if (typeof label !== 'string' && typeof label !== 'function') return;
705-
if (!Object.prototype.hasOwnProperty.call(this._schema, key)) return;
706741

707-
this._schema[key].label = label;
708-
this._depsLabels[key] && this._depsLabels[key].changed();
742+
const [schemaInstance, innerKey] = this.nearestSimpleSchemaInstance(key);
743+
if (!schemaInstance) return;
744+
745+
schemaInstance._schema[innerKey].label = label;
746+
schemaInstance._depsLabels[innerKey] && schemaInstance._depsLabels[innerKey].changed();
709747
});
710748
}
711749

package/lib/SimpleSchema_labels.tests.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ describe('SimpleSchema - label', function () {
1111
'obj.someString': { type: String },
1212
});
1313

14-
expect(schema.label('minMaxNumber')).toEqual('Min max number');
15-
expect(schema.label('obj.someString')).toEqual('Some string');
14+
expect(schema.label('minMaxNumber')).toBe('Min max number');
15+
expect(schema.label('obj.someString')).toBe('Some string');
1616
});
1717

1818
it('dynamic', function () {
@@ -22,13 +22,13 @@ describe('SimpleSchema - label', function () {
2222
'obj.someString': { type: String },
2323
});
2424

25-
expect(schema.label('obj.someString')).toEqual('Some string');
25+
expect(schema.label('obj.someString')).toBe('Some string');
2626

2727
schema.labels({
2828
'obj.someString': 'A different label',
2929
});
3030

31-
expect(schema.label('obj.someString')).toEqual('A different label');
31+
expect(schema.label('obj.someString')).toBe('A different label');
3232
});
3333

3434
it('callback', function () {
@@ -38,13 +38,13 @@ describe('SimpleSchema - label', function () {
3838
'obj.someString': { type: String },
3939
});
4040

41-
expect(schema.label('obj.someString')).toEqual('Some string');
41+
expect(schema.label('obj.someString')).toBe('Some string');
4242

4343
schema.labels({
4444
'obj.someString': () => 'A callback label',
4545
});
4646

47-
expect(schema.label('obj.someString')).toEqual('A callback label');
47+
expect(schema.label('obj.someString')).toBe('A callback label');
4848
});
4949

5050
it('should allow apostrophes ("\'") in labels', () => {
@@ -54,6 +54,24 @@ describe('SimpleSchema - label', function () {
5454
label: 'Manager/supervisor\'s name',
5555
},
5656
});
57-
expect(schema.label('foo')).toEqual('Manager/supervisor\'s name');
57+
expect(schema.label('foo')).toBe('Manager/supervisor\'s name');
58+
});
59+
60+
it('can set label of field in nested schema', function () {
61+
const objSchema = new SimpleSchema({
62+
someString: String,
63+
});
64+
65+
const schema = new SimpleSchema({
66+
obj: objSchema,
67+
});
68+
69+
expect(schema.label('obj.someString')).toBe('Some string');
70+
71+
schema.labels({
72+
'obj.someString': 'New label',
73+
});
74+
75+
expect(schema.label('obj.someString')).toBe('New label');
5876
});
5977
});

0 commit comments

Comments
 (0)