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.
@@ -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;