ember-data-factory-guy 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  });
@@ -0,0 +1,8 @@
1
+ Hat = DS.Model.extend({
2
+ type: DS.attr('string'),
3
+ user: DS.belongsTo('user')
4
+ })
5
+
6
+ BigHat = Hat.extend()
7
+ SmallHat = Hat.extend()
8
+
@@ -1,4 +1,5 @@
1
1
  User = DS.Model.extend({
2
2
  name: DS.attr('string'),
3
- projects: DS.hasMany('project')
3
+ projects: DS.hasMany('project'),
4
+ hats: DS.hasMany('hat', {polymorphic: true})
4
5
  })
@@ -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
- // convert attributes that are functions to strings
69
+ // deal with attributes that are functions or objects
70
70
  for (attribute in fixture) {
71
- if (typeof fixture[attribute] == 'function') {
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 object
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
- Given a name like 'person' or 'dude' determine what model this name
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
- lookupModelForName: function (name) {
226
- for (model in this.modelDefinitions) {
227
- var definition = this.modelDefinitions[model];
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} definition associated with model
264
+ @returns {ModelDefinition} ModelDefinition associated with model or undefined if not found
239
265
  */
240
- lookupDefinitionForName: function (name) {
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 fixture name
257
- @param {Object} opts options that will override default fixture values
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.lookupDefinitionForName(name);
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.lookupDefinitionForName(name);
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.lookupModelForName(name);
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.setBelongsToFixturesAdapter(modelType, modelName, fixture);
382
+ this.setAssociationsForFixtureAdapter(modelType, modelName, fixture);
364
383
  return FactoryGuy.pushFixture(modelType, fixture);
365
384
  } else {
366
- var self = this;
385
+ var store = this;
367
386
  var model;
368
387
  Em.run(function () {
369
- model = self.push(modelName, fixture);
370
- self.setBelongsToRESTAdapter(modelType, modelName, model);
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 association for FixtureAdapter,
394
- with models that have a hasMany association.
418
+ Set the hasMany and belongsTo associations for FixtureAdapter.
395
419
 
396
- For example if a user hasMany projects, then set the user.id
397
- on each project that the user hasMany of, so that the project
398
- now has the belongsTo user association setup.
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
- @param {String} modelType model type like App.User
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} parentFixture parent to assign as belongTo
441
+ @param {Object} fixture to check for needed association assignments
403
442
  */
404
- setBelongsToFixturesAdapter: function(modelType, modelName, fixture) {
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
- var hasManyName = self.findHasManyRelationshipName2(relationship.type, relationship.parentType);
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
- For the REST type models:
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
- Set the belongsTo association with a hasMany association
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
- Set this model in the parent hasMany array this model belongsTo
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
- setBelongsToRESTAdapter: function (modelType, modelName, model) {
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(belongsToRecord, model)
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
- findHasManyRelationshipName2: function (belongToModel, childModel) {
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(belongToModel.constructor, 'relationshipsByName').forEach(
551
+ Ember.get(belongToModelType, 'relationshipsByName').forEach(
483
552
  function (name, relationship) {
484
553
  if (relationship.kind == 'hasMany' &&
485
- relationship.type == childModel.constructor) {
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(belongsToRecord, record);
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.lookupModelForName(name);
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.lookupModelForName(name);
730
+ var model = FactoryGuy.lookupModelForFixtureName(name);
659
731
  var hash = {};
660
732
  hash[model] = fixture;
661
733
  return hash;