ember-data-factory-guy 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -1
- data/Gruntfile.js +8 -0
- data/README.md +253 -91
- data/bower.json +1 -1
- data/dist/ember-data-factory-guy.js +137 -65
- data/dist/ember-data-factory-guy.min.js +1 -1
- data/ember-data-factory-guy.gemspec +1 -1
- data/package.json +1 -1
- data/src/factory_guy.js +38 -24
- data/src/factory_guy_test_mixin.js +2 -2
- data/src/model_definition.js +7 -2
- data/src/store.js +90 -37
- data/tests/active_model_adapter_factory_test.js +26 -3
- data/tests/factory_guy_test.js +28 -2
- data/tests/fixture_adapter_factory_test.js +23 -0
- data/tests/rest_adapter_factory_test.js +27 -4
- data/tests/store_test.js +1 -1
- data/tests/support/factories/hat_factory.js +9 -0
- data/tests/support/factories/project_factory.js +12 -0
- data/tests/support/models/hat.js +8 -0
- data/tests/support/models/user.js +2 -1
- data/tests/support/test_helper.js +3 -0
- data/tests/test_setup.js +32 -1
- data/vendor/assets/javascripts/ember_data_factory_guy.js +137 -65
- metadata +4 -2
@@ -1,5 +1,17 @@
|
|
1
1
|
FactoryGuy.define('project', {
|
2
2
|
default: {
|
3
3
|
title: 'Project'
|
4
|
+
},
|
5
|
+
project_with_user: {
|
6
|
+
// user model with default attributes
|
7
|
+
user: {}
|
8
|
+
},
|
9
|
+
project_with_dude: {
|
10
|
+
// user model with custom attributes
|
11
|
+
user: {name: 'Dude'}
|
12
|
+
},
|
13
|
+
project_with_admin: {
|
14
|
+
// for named association, use this FactoryGuy.association helper method
|
15
|
+
user: FactoryGuy.association('admin')
|
4
16
|
}
|
5
17
|
});
|
@@ -9,6 +9,9 @@ TestHelper = Ember.Object.createWithMixins(FactoryGuyTestMixin,{
|
|
9
9
|
var container = new Ember.Container();
|
10
10
|
this.set('container', container);
|
11
11
|
|
12
|
+
container.register("model:hat", Hat);
|
13
|
+
container.register("model:small_hat", SmallHat);
|
14
|
+
container.register("model:big_hat", BigHat);
|
12
15
|
container.register("model:user", User);
|
13
16
|
container.register("model:project", Project);
|
14
17
|
container.register("store:main", DS.Store.extend({adapter: adapter}));
|
data/tests/test_setup.js
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
+
FactoryGuy.define('hat', {
|
2
|
+
default: {},
|
3
|
+
small_hat: {
|
4
|
+
type: 'small_hat'
|
5
|
+
},
|
6
|
+
big_hat: {
|
7
|
+
type: 'big_hat'
|
8
|
+
}
|
9
|
+
})
|
1
10
|
FactoryGuy.define('project', {
|
2
11
|
default: {
|
3
12
|
title: 'Project'
|
13
|
+
},
|
14
|
+
project_with_user: {
|
15
|
+
// user model with default attributes
|
16
|
+
user: {}
|
17
|
+
},
|
18
|
+
project_with_dude: {
|
19
|
+
// user model with custom attributes
|
20
|
+
user: {name: 'Dude'}
|
21
|
+
},
|
22
|
+
project_with_admin: {
|
23
|
+
// for named association, use this FactoryGuy.association helper method
|
24
|
+
user: FactoryGuy.association('admin')
|
4
25
|
}
|
5
26
|
});
|
6
27
|
FactoryGuy.define('user', {
|
@@ -13,6 +34,15 @@ FactoryGuy.define('user', {
|
|
13
34
|
name: 'Admin'
|
14
35
|
}
|
15
36
|
});
|
37
|
+
Hat = DS.Model.extend({
|
38
|
+
type: DS.attr('string'),
|
39
|
+
user: DS.belongsTo('user')
|
40
|
+
})
|
41
|
+
|
42
|
+
BigHat = Hat.extend()
|
43
|
+
SmallHat = Hat.extend()
|
44
|
+
|
45
|
+
|
16
46
|
Project = DS.Model.extend({
|
17
47
|
title: DS.attr('string'),
|
18
48
|
user: DS.belongsTo('user')
|
@@ -20,7 +50,8 @@ Project = DS.Model.extend({
|
|
20
50
|
|
21
51
|
User = DS.Model.extend({
|
22
52
|
name: DS.attr('string'),
|
23
|
-
projects: DS.hasMany('project')
|
53
|
+
projects: DS.hasMany('project'),
|
54
|
+
hats: DS.hasMany('hat', {polymorphic: true})
|
24
55
|
})
|
25
56
|
/**
|
26
57
|
* Sinon.JS 1.6.0, 2013/02/18
|
@@ -66,10 +66,15 @@ ModelDefinition = function (model, config) {
|
|
66
66
|
var modelAttributes = namedModels[name] || {};
|
67
67
|
// merge default, modelAttributes and opts to get the rough fixture
|
68
68
|
var fixture = $.extend({}, defaultAttributes, modelAttributes, opts);
|
69
|
-
//
|
69
|
+
// deal with attributes that are functions or objects
|
70
70
|
for (attribute in fixture) {
|
71
|
-
if (
|
71
|
+
if (Ember.typeOf(fixture[attribute]) == 'function') {
|
72
|
+
// function might be a sequence of a named association
|
72
73
|
fixture[attribute] = fixture[attribute].call(this, fixture);
|
74
|
+
} else if (Ember.typeOf(fixture[attribute]) == 'object') {
|
75
|
+
// if it's an object it's for a model association, so build the json
|
76
|
+
// for the association and replace the attribute with that json
|
77
|
+
fixture[attribute] = FactoryGuy.build(attribute, fixture[attribute])
|
73
78
|
}
|
74
79
|
}
|
75
80
|
// set the id, unless it was already set in opts
|
@@ -175,8 +180,8 @@ FactoryGuy = {
|
|
175
180
|
|
176
181
|
FactoryGuy.build('dude') or FactoryGuy.build('person')
|
177
182
|
|
178
|
-
@param model the model to define
|
179
|
-
@param config your model definition
|
183
|
+
@param {String} model the model to define
|
184
|
+
@param {Object} config your model definition
|
180
185
|
*/
|
181
186
|
define: function (model, config) {
|
182
187
|
if (this.modelDefinitions[model]) {
|
@@ -215,29 +220,50 @@ FactoryGuy = {
|
|
215
220
|
},
|
216
221
|
|
217
222
|
/**
|
218
|
-
|
223
|
+
Used in model definitions to define a belongsTo association attribute.
|
224
|
+
For example:
|
225
|
+
|
226
|
+
```
|
227
|
+
FactoryGuy.define('project', {
|
228
|
+
default: {
|
229
|
+
title: 'Project'
|
230
|
+
},
|
231
|
+
project_with_admin: {
|
232
|
+
// for named association, use this FactoryGuy.association helper method
|
233
|
+
user: FactoryGuy.association('admin')
|
234
|
+
}
|
235
|
+
|
236
|
+
```
|
237
|
+
|
238
|
+
@param {String} fixture name
|
239
|
+
@returns {Function} wrapper function that will build the association json
|
240
|
+
*/
|
241
|
+
association: function (fixtureName, opts) {
|
242
|
+
return function () {
|
243
|
+
return FactoryGuy.build(fixtureName, opts);
|
244
|
+
}
|
245
|
+
},
|
246
|
+
|
247
|
+
/**
|
248
|
+
Given a fixture name like 'person' or 'dude' determine what model this name
|
219
249
|
refers to. In this case it's 'person' for each one.
|
220
250
|
|
221
251
|
@param {String} name a fixture name could be model name like 'person'
|
222
252
|
or a named person in model definition like 'dude'
|
223
|
-
@returns {String} model name associated with fixture name
|
253
|
+
@returns {String} model name associated with fixture name or undefined if not found
|
224
254
|
*/
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
if (definition.matchesName(name)) {
|
229
|
-
return definition.model;
|
230
|
-
}
|
231
|
-
}
|
255
|
+
lookupModelForFixtureName: function (name) {
|
256
|
+
var definition = this.lookupDefinitionForFixtureName(name);
|
257
|
+
if (definition) { return definition.model; }
|
232
258
|
},
|
233
259
|
|
234
260
|
/**
|
235
261
|
|
236
262
|
@param {String} name a fixture name could be model name like 'person'
|
237
263
|
or a named person in model definition like 'dude'
|
238
|
-
@returns {ModelDefinition}
|
264
|
+
@returns {ModelDefinition} ModelDefinition associated with model or undefined if not found
|
239
265
|
*/
|
240
|
-
|
266
|
+
lookupDefinitionForFixtureName: function (name) {
|
241
267
|
for (model in this.modelDefinitions) {
|
242
268
|
var definition = this.modelDefinitions[model];
|
243
269
|
if (definition.matchesName(name)) {
|
@@ -253,12 +279,12 @@ FactoryGuy = {
|
|
253
279
|
FactoryGuy.build('user') for User model
|
254
280
|
FactoryGuy.build('bob') for User model with bob attributes
|
255
281
|
|
256
|
-
@param {String} name
|
257
|
-
@param {Object} opts
|
282
|
+
@param {String} name Fixture name
|
283
|
+
@param {Object} opts Options that will override default fixture values
|
258
284
|
@returns {Object} json fixture
|
259
285
|
*/
|
260
286
|
build: function (name, opts) {
|
261
|
-
var definition = this.
|
287
|
+
var definition = this.lookupDefinitionForFixtureName(name);
|
262
288
|
if (!definition) {
|
263
289
|
throw new Error("Can't find that factory named [" + name + "]");
|
264
290
|
}
|
@@ -277,7 +303,7 @@ FactoryGuy = {
|
|
277
303
|
@returns {Array} list of fixtures
|
278
304
|
*/
|
279
305
|
buildList: function (name, number, opts) {
|
280
|
-
var definition = this.
|
306
|
+
var definition = this.lookupDefinitionForFixtureName(name);
|
281
307
|
if (!definition) {
|
282
308
|
throw new Error("Can't find that factory named [" + name + "]");
|
283
309
|
}
|
@@ -291,7 +317,6 @@ FactoryGuy = {
|
|
291
317
|
Reset the id sequence for the models back to zero.
|
292
318
|
*/
|
293
319
|
resetModels: function (store) {
|
294
|
-
var typeMaps = store.typeMaps;
|
295
320
|
for (model in this.modelDefinitions) {
|
296
321
|
var definition = this.modelDefinitions[model];
|
297
322
|
definition.reset();
|
@@ -303,11 +328,6 @@ FactoryGuy = {
|
|
303
328
|
store.unloadAll(modelType);
|
304
329
|
} catch (e) {
|
305
330
|
}
|
306
|
-
// } else {
|
307
|
-
// for (model in typeMaps) {
|
308
|
-
// store.unloadAll(typeMaps[model].type);
|
309
|
-
// }
|
310
|
-
// }
|
311
331
|
}
|
312
332
|
},
|
313
333
|
|
@@ -333,7 +353,6 @@ FactoryGuy = {
|
|
333
353
|
clear: function (opts) {
|
334
354
|
if (!opts) {
|
335
355
|
this.modelDefinitions = {};
|
336
|
-
return;
|
337
356
|
}
|
338
357
|
}
|
339
358
|
}
|
@@ -355,19 +374,25 @@ DS.Store.reopen({
|
|
355
374
|
@returns {Object|DS.Model} json or record depending on the adapter type
|
356
375
|
*/
|
357
376
|
makeFixture: function (name, options) {
|
358
|
-
var modelName = FactoryGuy.
|
377
|
+
var modelName = FactoryGuy.lookupModelForFixtureName(name);
|
359
378
|
var fixture = FactoryGuy.build(name, options);
|
360
379
|
var modelType = this.modelFor(modelName);
|
361
380
|
|
362
381
|
if (this.usingFixtureAdapter()) {
|
363
|
-
this.
|
382
|
+
this.setAssociationsForFixtureAdapter(modelType, modelName, fixture);
|
364
383
|
return FactoryGuy.pushFixture(modelType, fixture);
|
365
384
|
} else {
|
366
|
-
var
|
385
|
+
var store = this;
|
367
386
|
var model;
|
368
387
|
Em.run(function () {
|
369
|
-
|
370
|
-
|
388
|
+
store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType, fixture);
|
389
|
+
if (fixture.type) {
|
390
|
+
// assuming its polymorphic if there is a type attribute
|
391
|
+
// is this too bold an assumption?
|
392
|
+
modelName = fixture.type
|
393
|
+
}
|
394
|
+
model = store.push(modelName, fixture);
|
395
|
+
store.setAssociationsForRESTAdapter(modelType, modelName, model);
|
371
396
|
});
|
372
397
|
return model;
|
373
398
|
}
|
@@ -390,18 +415,32 @@ DS.Store.reopen({
|
|
390
415
|
},
|
391
416
|
|
392
417
|
/**
|
393
|
-
Set the belongsTo
|
394
|
-
with models that have a hasMany association.
|
418
|
+
Set the hasMany and belongsTo associations for FixtureAdapter.
|
395
419
|
|
396
|
-
For example
|
397
|
-
|
398
|
-
|
420
|
+
For example, assuming a user hasMany projects, if you make a project,
|
421
|
+
then a user with that project in the users list of project, then this method
|
422
|
+
will go back and set the user.id on each project that the user hasMany of,
|
423
|
+
so that the project now has the belongsTo user association setup.
|
424
|
+
As in this scenario:
|
399
425
|
|
400
|
-
|
426
|
+
```js
|
427
|
+
var projectJson = store.makeFixture('project');
|
428
|
+
var userJson = store.makeFixture('user', {projects: [projectJson.id]});
|
429
|
+
```
|
430
|
+
|
431
|
+
Or if you make a project with a user, then set this project in
|
432
|
+
the users list of 'projects' it hasMany of. As in this scenario:
|
433
|
+
|
434
|
+
```js
|
435
|
+
var userJson = store.makeFixture('user');
|
436
|
+
var projectJson = store.makeFixture('project', {user: userJson.id});
|
437
|
+
```
|
438
|
+
|
439
|
+
@param {DS.Model} modelType model type like User
|
401
440
|
@param {String} modelName model name like 'user'
|
402
|
-
@param {Object}
|
441
|
+
@param {Object} fixture to check for needed association assignments
|
403
442
|
*/
|
404
|
-
|
443
|
+
setAssociationsForFixtureAdapter: function(modelType, modelName, fixture) {
|
405
444
|
var self = this;
|
406
445
|
var adapter = this.adapterFor('application');
|
407
446
|
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
@@ -418,7 +457,11 @@ DS.Store.reopen({
|
|
418
457
|
if (relationship.kind == 'belongsTo') {
|
419
458
|
var belongsToRecord = fixture[relationship.key];
|
420
459
|
if (belongsToRecord) {
|
421
|
-
|
460
|
+
if (typeof belongsToRecord == 'object') {
|
461
|
+
FactoryGuy.pushFixture(relationship.type, belongsToRecord);
|
462
|
+
fixture[relationship.key] = belongsToRecord.id;
|
463
|
+
}
|
464
|
+
var hasManyName = self.findHasManyRelationshipName(relationship.type, relationship.parentType);
|
422
465
|
var belongsToFixtures = adapter.fixturesForType(relationship.type);
|
423
466
|
var belongsTofixture = adapter.findFixtureById(belongsToFixtures, fixture[relationship.key]);
|
424
467
|
if (!belongsTofixture[hasManyName]) {
|
@@ -431,21 +474,56 @@ DS.Store.reopen({
|
|
431
474
|
},
|
432
475
|
|
433
476
|
/**
|
434
|
-
|
477
|
+
Before pushing the fixture to the store, do some preprocessing.
|
478
|
+
|
479
|
+
If its a belongs to association, and the fixture has an object there,
|
480
|
+
then push that model to the store and set the id of that new model
|
481
|
+
as the attribute value in the fixture
|
435
482
|
|
436
|
-
|
483
|
+
If it's a hasMany association, and its polymorphic, then convert the
|
484
|
+
attribute value to a polymorphic style
|
485
|
+
|
486
|
+
@param modelType
|
487
|
+
@param fixture
|
488
|
+
*/
|
489
|
+
findEmbeddedBelongsToAssociationsForRESTAdapter: function (modelType, fixture) {
|
490
|
+
var store = this;
|
491
|
+
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
492
|
+
if (relationship.kind == 'belongsTo') {
|
493
|
+
var belongsToRecord = fixture[relationship.key];
|
494
|
+
if (typeof belongsToRecord == 'object') {
|
495
|
+
belongsToRecord = store.push(relationship.type, belongsToRecord);
|
496
|
+
fixture[relationship.key] = belongsToRecord;
|
497
|
+
}
|
498
|
+
}
|
499
|
+
})
|
500
|
+
},
|
437
501
|
|
438
|
-
|
502
|
+
/**
|
503
|
+
For the REST type models:
|
439
504
|
|
440
505
|
For example if a user hasMany projects, then set the user
|
441
506
|
on each project that the user hasMany of, so that the project
|
442
|
-
now has the belongsTo user association setup
|
507
|
+
now has the belongsTo user association setup. As in this scenario:
|
508
|
+
|
509
|
+
```js
|
510
|
+
var project = store.makeFixture('project');
|
511
|
+
var user = store.makeFixture('user', {projects: [project]});
|
512
|
+
```
|
513
|
+
|
514
|
+
Or if you make a user, then a project with that user, then set the project
|
515
|
+
in the users list of 'projects' it hasMany of. As in this scenario:
|
516
|
+
|
517
|
+
```js
|
518
|
+
var user = store.makeFixture('user');
|
519
|
+
var project = store.makeFixture('project', {user: user});
|
520
|
+
```
|
443
521
|
|
444
522
|
@param {DS.Model} modelType model type like 'User'
|
445
523
|
@param {String} modelName model name like 'user'
|
446
|
-
@param {DS.Model} model
|
524
|
+
@param {DS.Model} model model to check for needed association assignments
|
447
525
|
*/
|
448
|
-
|
526
|
+
setAssociationsForRESTAdapter: function (modelType, modelName, model) {
|
449
527
|
var self = this;
|
450
528
|
Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
|
451
529
|
if (relationship.kind == 'hasMany') {
|
@@ -458,31 +536,22 @@ DS.Store.reopen({
|
|
458
536
|
if (relationship.kind == 'belongsTo') {
|
459
537
|
var belongsToRecord = model.get(name);
|
460
538
|
if (belongsToRecord) {
|
461
|
-
var hasManyName = self.findHasManyRelationshipName(
|
539
|
+
var hasManyName = self.findHasManyRelationshipName(
|
540
|
+
belongsToRecord.constructor,
|
541
|
+
model.constructor
|
542
|
+
)
|
462
543
|
belongsToRecord.get(hasManyName).addObject(model);
|
463
544
|
}
|
464
545
|
}
|
465
546
|
})
|
466
547
|
},
|
467
548
|
|
468
|
-
|
469
|
-
var relationshipName;
|
470
|
-
Ember.get(belongToModel, 'relationshipsByName').forEach(
|
471
|
-
function (name, relationship) {
|
472
|
-
if (relationship.kind == 'hasMany' &&
|
473
|
-
relationship.type == childModel) {
|
474
|
-
relationshipName = relationship.key;
|
475
|
-
}
|
476
|
-
}
|
477
|
-
)
|
478
|
-
return relationshipName;
|
479
|
-
},
|
480
|
-
findHasManyRelationshipName: function (belongToModel, childModel) {
|
549
|
+
findHasManyRelationshipName: function (belongToModelType, childModelType) {
|
481
550
|
var relationshipName;
|
482
|
-
Ember.get(
|
551
|
+
Ember.get(belongToModelType, 'relationshipsByName').forEach(
|
483
552
|
function (name, relationship) {
|
484
553
|
if (relationship.kind == 'hasMany' &&
|
485
|
-
relationship.type ==
|
554
|
+
relationship.type == childModelType) {
|
486
555
|
relationshipName = relationship.key;
|
487
556
|
}
|
488
557
|
}
|
@@ -558,7 +627,10 @@ DS.FixtureAdapter.reopen({
|
|
558
627
|
relationShips.belongsTo.forEach(function (relationship) {
|
559
628
|
var belongsToRecord = record.get(relationship);
|
560
629
|
if (belongsToRecord) {
|
561
|
-
var hasManyName = store.findHasManyRelationshipName(
|
630
|
+
var hasManyName = store.findHasManyRelationshipName(
|
631
|
+
belongsToRecord.constructor,
|
632
|
+
record.constructor
|
633
|
+
);
|
562
634
|
belongsToRecord.get(hasManyName).addObject(record);
|
563
635
|
}
|
564
636
|
})
|
@@ -639,7 +711,7 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
639
711
|
@param {Object} opts fixture options
|
640
712
|
*/
|
641
713
|
handleCreate: function (name, opts) {
|
642
|
-
var model = FactoryGuy.
|
714
|
+
var model = FactoryGuy.lookupModelForFixtureName(name);
|
643
715
|
this.stubEndpointForHttpRequest(
|
644
716
|
"/" + Em.String.pluralize(model),
|
645
717
|
this.buildAjaxCreateResponse(name, opts),
|
@@ -655,7 +727,7 @@ FactoryGuyTestMixin = Em.Mixin.create({
|
|
655
727
|
¬ */
|
656
728
|
buildAjaxCreateResponse: function (name, opts) {
|
657
729
|
var fixture = FactoryGuy.build(name, opts);
|
658
|
-
var model = FactoryGuy.
|
730
|
+
var model = FactoryGuy.lookupModelForFixtureName(name);
|
659
731
|
var hash = {};
|
660
732
|
hash[model] = fixture;
|
661
733
|
return hash;
|