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.
data/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-data-factory-guy",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
@@ -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;
@@ -1 +1 @@
1
- Sequence=function(fn){var index=1;this.next=function(){return fn.call(this,index++)};this.reset=function(){index=1}};function MissingSequenceError(message){this.toString=function(){return message}}ModelDefinition=function(model,config){var sequences={};var defaultAttributes={};var namedModels={};var modelId=1;this.model=model;this.matchesName=function(name){return model==name||namedModels[name]};this.merge=function(config){};this.generate=function(sequenceName){var sequence=sequences[sequenceName];if(!sequence){throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+model+"' definition")}return sequence.next()};this.build=function(name,opts){var modelAttributes=namedModels[name]||{};var fixture=$.extend({},defaultAttributes,modelAttributes,opts);for(attribute in fixture){if(typeof fixture[attribute]=="function"){fixture[attribute]=fixture[attribute].call(this,fixture)}}if(!fixture.id){fixture.id=modelId++}return fixture};this.buildList=function(name,number,opts){var arr=[];for(var i=0;i<number;i++){arr.push(this.build(name,opts))}return arr};this.reset=function(){modelId=1;for(name in sequences){sequences[name].reset()}};var parseDefault=function(object){if(!object){return}defaultAttributes=object};var parseSequences=function(object){if(!object){return}for(sequenceName in object){var sequenceFn=object[sequenceName];if(typeof sequenceFn!="function"){throw new Error("Problem with ["+sequenceName+"] sequence definition. Sequences must be functions")}object[sequenceName]=new Sequence(sequenceFn)}sequences=object};var parseConfig=function(config){parseSequences(config.sequences);delete config.sequences;parseDefault(config.default);delete config.default;namedModels=config};parseConfig(config)};FactoryGuy={modelDefinitions:{},define:function(model,config){if(this.modelDefinitions[model]){this.modelDefinitions[model].merge(config)}else{this.modelDefinitions[model]=new ModelDefinition(model,config)}},generate:function(sequenceName){return function(){return this.generate(sequenceName)}},lookupModelForName:function(name){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];if(definition.matchesName(name)){return definition.model}}},lookupDefinitionForName:function(name){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];if(definition.matchesName(name)){return definition}}},build:function(name,opts){var definition=this.lookupDefinitionForName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.build(name,opts)},buildList:function(name,number,opts){var definition=this.lookupDefinitionForName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.buildList(name,number,opts)},resetModels:function(store){var typeMaps=store.typeMaps;for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];definition.reset();try{var modelType=store.modelFor(definition.model);if(store.usingFixtureAdapter()){modelType.FIXTURES=[]}store.unloadAll(modelType)}catch(e){}}},pushFixture:function(modelClass,fixture){if(!modelClass["FIXTURES"]){modelClass["FIXTURES"]=[]}modelClass["FIXTURES"].push(fixture);return fixture},clear:function(opts){if(!opts){this.modelDefinitions={};return}}};DS.Store.reopen({usingFixtureAdapter:function(){var adapter=this.adapterFor("application");return adapter instanceof DS.FixtureAdapter},makeFixture:function(name,options){var modelName=FactoryGuy.lookupModelForName(name);var fixture=FactoryGuy.build(name,options);var modelType=this.modelFor(modelName);if(this.usingFixtureAdapter()){this.setBelongsToFixturesAdapter(modelType,modelName,fixture);return FactoryGuy.pushFixture(modelType,fixture)}else{var self=this;var model;Em.run(function(){model=self.push(modelName,fixture);self.setBelongsToRESTAdapter(modelType,modelName,model)});return model}},makeList:function(name,number,options){var arr=[];for(var i=0;i<number;i++){arr.push(this.makeFixture(name,options))}return arr},setBelongsToFixturesAdapter:function(modelType,modelName,fixture){var self=this;var adapter=this.adapterFor("application");Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){if(fixture[relationship.key]){fixture[relationship.key].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(relationship.type);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=fixture.id})}}if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(belongsToRecord){var hasManyName=self.findHasManyRelationshipName2(relationship.type,relationship.parentType);var belongsToFixtures=adapter.fixturesForType(relationship.type);var belongsTofixture=adapter.findFixtureById(belongsToFixtures,fixture[relationship.key]);if(!belongsTofixture[hasManyName]){belongsTofixture[hasManyName]=[]}belongsTofixture[hasManyName].push(fixture.id)}}})},setBelongsToRESTAdapter:function(modelType,modelName,model){var self=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){var children=model.get(name)||[];children.forEach(function(child){child.set(modelName,model)})}if(relationship.kind=="belongsTo"){var belongsToRecord=model.get(name);if(belongsToRecord){var hasManyName=self.findHasManyRelationshipName(belongsToRecord,model);belongsToRecord.get(hasManyName).addObject(model)}}})},findHasManyRelationshipName2:function(belongToModel,childModel){var relationshipName;Ember.get(belongToModel,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"&&relationship.type==childModel){relationshipName=relationship.key}});return relationshipName},findHasManyRelationshipName:function(belongToModel,childModel){var relationshipName;Ember.get(belongToModel.constructor,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"&&relationship.type==childModel.constructor){relationshipName=relationship.key}});return relationshipName},pushPayload:function(type,payload){if(this.usingFixtureAdapter()){var model=this.modelFor(modelName);FactoryGuy.pushFixture(model,payload)}else{this._super(type,payload)}}});DS.FixtureAdapter.reopen({createRecord:function(store,type,record){var promise=this._super(store,type,record);promise.then(function(){var relationShips=Ember.get(type,"relationshipNames");if(relationShips.belongsTo){relationShips.belongsTo.forEach(function(relationship){var belongsToRecord=record.get(relationship);if(belongsToRecord){var hasManyName=store.findHasManyRelationshipName(belongsToRecord,record);belongsToRecord.get(hasManyName).addObject(record)}})}});return promise}});FactoryGuyTestMixin=Em.Mixin.create({setup:function(app){this.set("container",app.__container__);return this},useFixtureAdapter:function(app){app.ApplicationAdapter=DS.FixtureAdapter;this.getStore().adapterFor("application").simulateRemoteResponse=false},find:function(type,id){return this.getStore().find(type,id)},make:function(name,opts){return this.getStore().makeFixture(name,opts)},getStore:function(){return this.get("container").lookup("store:main")},pushPayload:function(type,hash){return this.getStore().pushPayload(type,hash)},pushRecord:function(type,hash){return this.getStore().push(type,hash)},stubEndpointForHttpRequest:function(url,json,options){options=options||{};var request={url:url,dataType:"json",responseText:json,type:options.type||"GET",status:options.status||200};if(options.data){request.data=options.data}$.mockjax(request)},handleCreate:function(name,opts){var model=FactoryGuy.lookupModelForName(name);this.stubEndpointForHttpRequest("/"+Em.String.pluralize(model),this.buildAjaxCreateResponse(name,opts),{type:"POST"})},buildAjaxCreateResponse:function(name,opts){var fixture=FactoryGuy.build(name,opts);var model=FactoryGuy.lookupModelForName(name);var hash={};hash[model]=fixture;return hash},handleUpdate:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"PUT"})},handleDelete:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"DELETE"})},teardown:function(){FactoryGuy.resetModels(this.getStore())}});
1
+ Sequence=function(fn){var index=1;this.next=function(){return fn.call(this,index++)};this.reset=function(){index=1}};function MissingSequenceError(message){this.toString=function(){return message}}ModelDefinition=function(model,config){var sequences={};var defaultAttributes={};var namedModels={};var modelId=1;this.model=model;this.matchesName=function(name){return model==name||namedModels[name]};this.merge=function(config){};this.generate=function(sequenceName){var sequence=sequences[sequenceName];if(!sequence){throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+model+"' definition")}return sequence.next()};this.build=function(name,opts){var modelAttributes=namedModels[name]||{};var fixture=$.extend({},defaultAttributes,modelAttributes,opts);for(attribute in fixture){if(Ember.typeOf(fixture[attribute])=="function"){fixture[attribute]=fixture[attribute].call(this,fixture)}else if(Ember.typeOf(fixture[attribute])=="object"){fixture[attribute]=FactoryGuy.build(attribute,fixture[attribute])}}if(!fixture.id){fixture.id=modelId++}return fixture};this.buildList=function(name,number,opts){var arr=[];for(var i=0;i<number;i++){arr.push(this.build(name,opts))}return arr};this.reset=function(){modelId=1;for(name in sequences){sequences[name].reset()}};var parseDefault=function(object){if(!object){return}defaultAttributes=object};var parseSequences=function(object){if(!object){return}for(sequenceName in object){var sequenceFn=object[sequenceName];if(typeof sequenceFn!="function"){throw new Error("Problem with ["+sequenceName+"] sequence definition. Sequences must be functions")}object[sequenceName]=new Sequence(sequenceFn)}sequences=object};var parseConfig=function(config){parseSequences(config.sequences);delete config.sequences;parseDefault(config.default);delete config.default;namedModels=config};parseConfig(config)};FactoryGuy={modelDefinitions:{},define:function(model,config){if(this.modelDefinitions[model]){this.modelDefinitions[model].merge(config)}else{this.modelDefinitions[model]=new ModelDefinition(model,config)}},generate:function(sequenceName){return function(){return this.generate(sequenceName)}},association:function(fixtureName,opts){return function(){return FactoryGuy.build(fixtureName,opts)}},lookupModelForFixtureName:function(name){var definition=this.lookupDefinitionForFixtureName(name);if(definition){return definition.model}},lookupDefinitionForFixtureName:function(name){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];if(definition.matchesName(name)){return definition}}},build:function(name,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.build(name,opts)},buildList:function(name,number,opts){var definition=this.lookupDefinitionForFixtureName(name);if(!definition){throw new Error("Can't find that factory named ["+name+"]")}return definition.buildList(name,number,opts)},resetModels:function(store){for(model in this.modelDefinitions){var definition=this.modelDefinitions[model];definition.reset();try{var modelType=store.modelFor(definition.model);if(store.usingFixtureAdapter()){modelType.FIXTURES=[]}store.unloadAll(modelType)}catch(e){}}},pushFixture:function(modelClass,fixture){if(!modelClass["FIXTURES"]){modelClass["FIXTURES"]=[]}modelClass["FIXTURES"].push(fixture);return fixture},clear:function(opts){if(!opts){this.modelDefinitions={}}}};DS.Store.reopen({usingFixtureAdapter:function(){var adapter=this.adapterFor("application");return adapter instanceof DS.FixtureAdapter},makeFixture:function(name,options){var modelName=FactoryGuy.lookupModelForFixtureName(name);var fixture=FactoryGuy.build(name,options);var modelType=this.modelFor(modelName);if(this.usingFixtureAdapter()){this.setAssociationsForFixtureAdapter(modelType,modelName,fixture);return FactoryGuy.pushFixture(modelType,fixture)}else{var store=this;var model;Em.run(function(){store.findEmbeddedBelongsToAssociationsForRESTAdapter(modelType,fixture);if(fixture.type){modelName=fixture.type}model=store.push(modelName,fixture);store.setAssociationsForRESTAdapter(modelType,modelName,model)});return model}},makeList:function(name,number,options){var arr=[];for(var i=0;i<number;i++){arr.push(this.makeFixture(name,options))}return arr},setAssociationsForFixtureAdapter:function(modelType,modelName,fixture){var self=this;var adapter=this.adapterFor("application");Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){if(fixture[relationship.key]){fixture[relationship.key].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(relationship.type);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=fixture.id})}}if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(belongsToRecord){if(typeof belongsToRecord=="object"){FactoryGuy.pushFixture(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord.id}var hasManyName=self.findHasManyRelationshipName(relationship.type,relationship.parentType);var belongsToFixtures=adapter.fixturesForType(relationship.type);var belongsTofixture=adapter.findFixtureById(belongsToFixtures,fixture[relationship.key]);if(!belongsTofixture[hasManyName]){belongsTofixture[hasManyName]=[]}belongsTofixture[hasManyName].push(fixture.id)}}})},findEmbeddedBelongsToAssociationsForRESTAdapter:function(modelType,fixture){var store=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="belongsTo"){var belongsToRecord=fixture[relationship.key];if(typeof belongsToRecord=="object"){belongsToRecord=store.push(relationship.type,belongsToRecord);fixture[relationship.key]=belongsToRecord}}})},setAssociationsForRESTAdapter:function(modelType,modelName,model){var self=this;Ember.get(modelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"){var children=model.get(name)||[];children.forEach(function(child){child.set(modelName,model)})}if(relationship.kind=="belongsTo"){var belongsToRecord=model.get(name);if(belongsToRecord){var hasManyName=self.findHasManyRelationshipName(belongsToRecord.constructor,model.constructor);belongsToRecord.get(hasManyName).addObject(model)}}})},findHasManyRelationshipName:function(belongToModelType,childModelType){var relationshipName;Ember.get(belongToModelType,"relationshipsByName").forEach(function(name,relationship){if(relationship.kind=="hasMany"&&relationship.type==childModelType){relationshipName=relationship.key}});return relationshipName},pushPayload:function(type,payload){if(this.usingFixtureAdapter()){var model=this.modelFor(modelName);FactoryGuy.pushFixture(model,payload)}else{this._super(type,payload)}}});DS.FixtureAdapter.reopen({createRecord:function(store,type,record){var promise=this._super(store,type,record);promise.then(function(){var relationShips=Ember.get(type,"relationshipNames");if(relationShips.belongsTo){relationShips.belongsTo.forEach(function(relationship){var belongsToRecord=record.get(relationship);if(belongsToRecord){var hasManyName=store.findHasManyRelationshipName(belongsToRecord.constructor,record.constructor);belongsToRecord.get(hasManyName).addObject(record)}})}});return promise}});FactoryGuyTestMixin=Em.Mixin.create({setup:function(app){this.set("container",app.__container__);return this},useFixtureAdapter:function(app){app.ApplicationAdapter=DS.FixtureAdapter;this.getStore().adapterFor("application").simulateRemoteResponse=false},find:function(type,id){return this.getStore().find(type,id)},make:function(name,opts){return this.getStore().makeFixture(name,opts)},getStore:function(){return this.get("container").lookup("store:main")},pushPayload:function(type,hash){return this.getStore().pushPayload(type,hash)},pushRecord:function(type,hash){return this.getStore().push(type,hash)},stubEndpointForHttpRequest:function(url,json,options){options=options||{};var request={url:url,dataType:"json",responseText:json,type:options.type||"GET",status:options.status||200};if(options.data){request.data=options.data}$.mockjax(request)},handleCreate:function(name,opts){var model=FactoryGuy.lookupModelForFixtureName(name);this.stubEndpointForHttpRequest("/"+Em.String.pluralize(model),this.buildAjaxCreateResponse(name,opts),{type:"POST"})},buildAjaxCreateResponse:function(name,opts){var fixture=FactoryGuy.build(name,opts);var model=FactoryGuy.lookupModelForFixtureName(name);var hash={};hash[model]=fixture;return hash},handleUpdate:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"PUT"})},handleDelete:function(root,id){this.stubEndpointForHttpRequest("/"+Em.String.pluralize(root)+"/"+id,{},{type:"DELETE"})},teardown:function(){FactoryGuy.resetModels(this.getStore())}});
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = "ember-data-factory-guy"
4
- s.version = "0.2.1"
4
+ s.version = "0.3.0"
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ["Daniel Sudol", "Alex Opak"]
7
7
  s.email = ["dansudol@yahoo.com", "opak.alexandr@gmail.com"]
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-data-factory-guy",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
data/src/factory_guy.js CHANGED
@@ -36,8 +36,8 @@ FactoryGuy = {
36
36
 
37
37
  FactoryGuy.build('dude') or FactoryGuy.build('person')
38
38
 
39
- @param model the model to define
40
- @param config your model definition object
39
+ @param {String} model the model to define
40
+ @param {Object} config your model definition
41
41
  */
42
42
  define: function (model, config) {
43
43
  if (this.modelDefinitions[model]) {
@@ -76,29 +76,50 @@ FactoryGuy = {
76
76
  },
77
77
 
78
78
  /**
79
- Given a name like 'person' or 'dude' determine what model this name
79
+ Used in model definitions to define a belongsTo association attribute.
80
+ For example:
81
+
82
+ ```
83
+ FactoryGuy.define('project', {
84
+ default: {
85
+ title: 'Project'
86
+ },
87
+ project_with_admin: {
88
+ // for named association, use this FactoryGuy.association helper method
89
+ user: FactoryGuy.association('admin')
90
+ }
91
+
92
+ ```
93
+
94
+ @param {String} fixture name
95
+ @returns {Function} wrapper function that will build the association json
96
+ */
97
+ association: function (fixtureName, opts) {
98
+ return function () {
99
+ return FactoryGuy.build(fixtureName, opts);
100
+ }
101
+ },
102
+
103
+ /**
104
+ Given a fixture name like 'person' or 'dude' determine what model this name
80
105
  refers to. In this case it's 'person' for each one.
81
106
 
82
107
  @param {String} name a fixture name could be model name like 'person'
83
108
  or a named person in model definition like 'dude'
84
- @returns {String} model name associated with fixture name
109
+ @returns {String} model name associated with fixture name or undefined if not found
85
110
  */
86
- lookupModelForName: function (name) {
87
- for (model in this.modelDefinitions) {
88
- var definition = this.modelDefinitions[model];
89
- if (definition.matchesName(name)) {
90
- return definition.model;
91
- }
92
- }
111
+ lookupModelForFixtureName: function (name) {
112
+ var definition = this.lookupDefinitionForFixtureName(name);
113
+ if (definition) { return definition.model; }
93
114
  },
94
115
 
95
116
  /**
96
117
 
97
118
  @param {String} name a fixture name could be model name like 'person'
98
119
  or a named person in model definition like 'dude'
99
- @returns {ModelDefinition} definition associated with model
120
+ @returns {ModelDefinition} ModelDefinition associated with model or undefined if not found
100
121
  */
101
- lookupDefinitionForName: function (name) {
122
+ lookupDefinitionForFixtureName: function (name) {
102
123
  for (model in this.modelDefinitions) {
103
124
  var definition = this.modelDefinitions[model];
104
125
  if (definition.matchesName(name)) {
@@ -114,12 +135,12 @@ FactoryGuy = {
114
135
  FactoryGuy.build('user') for User model
115
136
  FactoryGuy.build('bob') for User model with bob attributes
116
137
 
117
- @param {String} name fixture name
118
- @param {Object} opts options that will override default fixture values
138
+ @param {String} name Fixture name
139
+ @param {Object} opts Options that will override default fixture values
119
140
  @returns {Object} json fixture
120
141
  */
121
142
  build: function (name, opts) {
122
- var definition = this.lookupDefinitionForName(name);
143
+ var definition = this.lookupDefinitionForFixtureName(name);
123
144
  if (!definition) {
124
145
  throw new Error("Can't find that factory named [" + name + "]");
125
146
  }
@@ -138,7 +159,7 @@ FactoryGuy = {
138
159
  @returns {Array} list of fixtures
139
160
  */
140
161
  buildList: function (name, number, opts) {
141
- var definition = this.lookupDefinitionForName(name);
162
+ var definition = this.lookupDefinitionForFixtureName(name);
142
163
  if (!definition) {
143
164
  throw new Error("Can't find that factory named [" + name + "]");
144
165
  }
@@ -152,7 +173,6 @@ FactoryGuy = {
152
173
  Reset the id sequence for the models back to zero.
153
174
  */
154
175
  resetModels: function (store) {
155
- var typeMaps = store.typeMaps;
156
176
  for (model in this.modelDefinitions) {
157
177
  var definition = this.modelDefinitions[model];
158
178
  definition.reset();
@@ -164,11 +184,6 @@ FactoryGuy = {
164
184
  store.unloadAll(modelType);
165
185
  } catch (e) {
166
186
  }
167
- // } else {
168
- // for (model in typeMaps) {
169
- // store.unloadAll(typeMaps[model].type);
170
- // }
171
- // }
172
187
  }
173
188
  },
174
189
 
@@ -194,7 +209,6 @@ FactoryGuy = {
194
209
  clear: function (opts) {
195
210
  if (!opts) {
196
211
  this.modelDefinitions = {};
197
- return;
198
212
  }
199
213
  }
200
214
  }