ember-data-factory-guy 0.1.3 → 0.2.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 +1 @@
1
- Sequence=function(fn){var index=1;var fn=fn;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){if(!sequences[sequenceName]){throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+model+"' definition")}return sequences[sequenceName].next()};this.build=function(name,opts){var modelAttributes=namedModels[name]||{};var fixture=$.extend({},defaultAttributes,modelAttributes,opts);for(attr in fixture){if(typeof fixture[attr]=="function"){fixture[attr]=fixture[attr].call(this)}}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};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}};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,parentFixture){var store=this;var adapter=this.adapterFor("application");var relationShips=Ember.get(modelType,"relationshipNames");if(relationShips.hasMany){relationShips.hasMany.forEach(function(relationship){var hasManyModel=store.modelFor(Em.String.singularize(relationship));if(parentFixture[relationship]){parentFixture[relationship].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(hasManyModel);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=parentFixture.id})}})}},setBelongsToRESTAdapter:function(modelType,modelName,parent){var relationShips=Ember.get(modelType,"relationshipNames");if(relationShips.hasMany){relationShips.hasMany.forEach(function(name){var children=parent.get(name);if(children.get("length")>0){children.forEach(function(child){child.set(modelName,parent)})}})}},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);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.buildAjaxResponse(name,opts),{type:"POST"})},buildAjaxResponse: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(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,parentFixture){var store=this;var adapter=this.adapterFor("application");var relationShips=Ember.get(modelType,"relationshipNames");if(relationShips.hasMany){relationShips.hasMany.forEach(function(relationship){var hasManyModel=store.modelFor(Em.String.singularize(relationship));if(parentFixture[relationship]){parentFixture[relationship].forEach(function(id){var hasManyfixtures=adapter.fixturesForType(hasManyModel);var fixture=adapter.findFixtureById(hasManyfixtures,id);fixture[modelName]=parentFixture.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)}}})},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,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.1.3"
4
+ s.version = "0.2.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.1.3",
3
+ "version": "0.2.0",
4
4
  "authors": [
5
5
  "Daniel Sudol <dansudol@yahoo.com>",
6
6
  "Opak Alex <opak.alexandr@gmail.com>"
@@ -14,28 +14,23 @@
14
14
  "FixtureAdapter"
15
15
  ],
16
16
  "license": "MIT",
17
-
18
17
  "bugs": {
19
18
  "url": ""
20
19
  },
21
-
22
20
  "scripts": {
23
21
  "test": "grunt test"
24
22
  },
25
-
26
23
  "repository": {
27
24
  "type": "git",
28
25
  "url": ""
29
26
  },
30
-
31
27
  "devDependencies": [
32
28
  "grunt-contrib-coffee",
33
29
  "grunt-contrib-concat",
34
30
  "grunt-contrib-uglify",
35
31
  "grunt-contrib-qunit"
36
32
  ],
37
-
38
33
  "engines": {
39
34
  "node": ">=v0.10.1"
40
35
  }
41
- }
36
+ }
data/src/factory_guy.js CHANGED
@@ -29,12 +29,12 @@ FactoryGuy = {
29
29
 
30
30
  ```
31
31
 
32
- For the Person model, you can define fixtures like 'dude' or just use 'person'
33
- and get default values.
32
+ For the Person model, you can define named fixtures like 'dude' or
33
+ just use 'person' and get default values.
34
34
 
35
35
  And to get those fixtures you would call them this way:
36
36
 
37
- FactoryGuy.build('person') or FactoryGuy.build('dude')
37
+ FactoryGuy.build('dude') or FactoryGuy.build('person')
38
38
 
39
39
  @param model the model to define
40
40
  @param config your model definition object
@@ -47,18 +47,41 @@ FactoryGuy = {
47
47
  }
48
48
  },
49
49
 
50
+ /**
51
+ Used in model definitions to declare use of a sequence. For example:
52
+
53
+ ```
54
+
55
+ FactoryGuy.define('person', {
56
+ sequences: {
57
+ personName: function(num) {
58
+ return 'person #' + num;
59
+ }
60
+ },
61
+ default: {
62
+ name: FactoryGuy.generate('personName')
63
+ }
64
+ });
65
+
66
+ ```
67
+
68
+ @param {String} sequenceName
69
+ @returns {Function} wrapper function that is called by the model
70
+ definition containing the sequence
71
+ */
50
72
  generate: function (sequenceName) {
51
73
  return function () {
52
74
  return this.generate(sequenceName);
53
75
  }
54
76
  },
55
77
 
56
-
57
78
  /**
79
+ Given a name like 'person' or 'dude' determine what model this name
80
+ refers to. In this case it's 'person' for each one.
58
81
 
59
- @param name fixture name could be model name like 'user'
60
- or specific user like 'admin'
61
- @returns model associated with fixture name
82
+ @param {String} name a fixture name could be model name like 'person'
83
+ or a named person in model definition like 'dude'
84
+ @returns {String} model name associated with fixture name
62
85
  */
63
86
  lookupModelForName: function (name) {
64
87
  for (model in this.modelDefinitions) {
@@ -71,9 +94,9 @@ FactoryGuy = {
71
94
 
72
95
  /**
73
96
 
74
- @param name fixture name could be model name like 'user'
75
- or specific user like 'admin'
76
- @returns definition associated with model
97
+ @param {String} name a fixture name could be model name like 'person'
98
+ or a named person in model definition like 'dude'
99
+ @returns {ModelDefinition} definition associated with model
77
100
  */
78
101
  lookupDefinitionForName: function (name) {
79
102
  for (model in this.modelDefinitions) {
@@ -91,9 +114,9 @@ FactoryGuy = {
91
114
  FactoryGuy.build('user') for User model
92
115
  FactoryGuy.build('bob') for User model with bob attributes
93
116
 
94
- @param name fixture name
95
- @param opts options that will override default fixture values
96
- @returns {*}
117
+ @param {String} name fixture name
118
+ @param {Object} opts options that will override default fixture values
119
+ @returns {Object} json fixture
97
120
  */
98
121
  build: function (name, opts) {
99
122
  var definition = this.lookupDefinitionForName(name);
@@ -109,10 +132,10 @@ FactoryGuy = {
109
132
  FactoryGuy.buildList('user', 2) for 2 User models
110
133
  FactoryGuy.build('bob', 2) for 2 User model with bob attributes
111
134
 
112
- @param name fixture name
113
- @param number number of fixtures to create
114
- @param opts options that will override default fixture values
115
- @returns list of fixtures
135
+ @param {String} name fixture name
136
+ @param {Number} number number of fixtures to create
137
+ @param {Object} opts options that will override default fixture values
138
+ @returns {Array} list of fixtures
116
139
  */
117
140
  buildList: function (name, number, opts) {
118
141
  var definition = this.lookupDefinitionForName(name);
@@ -123,9 +146,11 @@ FactoryGuy = {
123
146
  },
124
147
 
125
148
  /**
149
+ TODO: This is kind of problematic right now .. needs work
150
+
126
151
  Clear model instances from FIXTURES array, and from store cache.
127
152
  Reset the id sequence for the models back to zero.
128
- */
153
+ */
129
154
  resetModels: function (store) {
130
155
  var typeMaps = store.typeMaps;
131
156
  for (model in this.modelDefinitions) {
@@ -144,9 +169,6 @@ FactoryGuy = {
144
169
  // store.unloadAll(typeMaps[model].type);
145
170
  // }
146
171
  // }
147
-
148
- // for (model in this.modelDefinitions) {
149
- // this.modelDefinitions[model].reset();
150
172
  }
151
173
  },
152
174
 
@@ -154,9 +176,9 @@ FactoryGuy = {
154
176
  Push fixture to model's FIXTURES array.
155
177
  Used when store's adapter is a DS.FixtureAdapter.
156
178
 
157
- @param modelClass DS.Model type
158
- @param fixture the fixture to add
159
- @returns json fixture data
179
+ @param {DS.Model} modelClass
180
+ @param {Object} fixture the fixture to add
181
+ @returns {Object} json fixture data
160
182
  */
161
183
  pushFixture: function (modelClass, fixture) {
162
184
  if (!modelClass['FIXTURES']) {
@@ -164,5 +186,15 @@ FactoryGuy = {
164
186
  }
165
187
  modelClass['FIXTURES'].push(fixture);
166
188
  return fixture;
189
+ },
190
+
191
+ /**
192
+ Clears all model definitions
193
+ */
194
+ clear: function (opts) {
195
+ if (!opts) {
196
+ this.modelDefinitions = {};
197
+ return;
198
+ }
167
199
  }
168
200
  }
@@ -11,6 +11,13 @@ FactoryGuyTestMixin = Em.Mixin.create({
11
11
  this.getStore().adapterFor('application').simulateRemoteResponse = false;
12
12
  },
13
13
 
14
+ /**
15
+ Proxy to store's find method
16
+
17
+ @param {String or subclass of DS.Model} type
18
+ @param {Object|String|Integer|null} id
19
+ @return {Promise} promise
20
+ */
14
21
  find: function(type, id) {
15
22
  return this.getStore().find(type, id);
16
23
  },
@@ -31,6 +38,13 @@ FactoryGuyTestMixin = Em.Mixin.create({
31
38
  return this.getStore().push(type, hash);
32
39
  },
33
40
 
41
+ /**
42
+ Using mockjax to stub an http request.
43
+
44
+ @param {String} url request url
45
+ @param {Object} json response
46
+ @param {Object} options ajax request options
47
+ */
34
48
  stubEndpointForHttpRequest: function (url, json, options) {
35
49
  options = options || {};
36
50
  var request = {
@@ -49,21 +63,27 @@ FactoryGuyTestMixin = Em.Mixin.create({
49
63
  },
50
64
 
51
65
  /**
52
- * Handling ajax POST for a model
53
- *
54
- * @param name of the fixture ( or model ) to create
55
- * @param opts fixture options
66
+ Handling ajax POST ( create record ) for a model
67
+
68
+ @param {String} name of the fixture ( or model ) to create
69
+ @param {Object} opts fixture options
56
70
  */
57
71
  handleCreate: function (name, opts) {
58
72
  var model = FactoryGuy.lookupModelForName(name);
59
73
  this.stubEndpointForHttpRequest(
60
74
  "/" + Em.String.pluralize(model),
61
- this.buildAjaxResponse(name, opts),
75
+ this.buildAjaxCreateResponse(name, opts),
62
76
  {type: 'POST'}
63
77
  )
64
78
  },
65
79
 
66
- buildAjaxResponse: function (name, opts) {
80
+ /**
81
+ Build the json used for creating record
82
+
83
+ @param {String} name of the fixture ( or model ) to create
84
+ @param {Object} opts fixture options
85
+ ¬ */
86
+ buildAjaxCreateResponse: function (name, opts) {
67
87
  var fixture = FactoryGuy.build(name, opts);
68
88
  var model = FactoryGuy.lookupModelForName(name);
69
89
  var hash = {};
@@ -86,5 +106,4 @@ FactoryGuyTestMixin = Em.Mixin.create({
86
106
  teardown: function () {
87
107
  FactoryGuy.resetModels(this.getStore());
88
108
  }
89
-
90
109
  })
@@ -1,3 +1,10 @@
1
+ /**
2
+ A ModelDefinition encapsulates a model's definition
3
+
4
+ @param model
5
+ @param config
6
+ @constructor
7
+ */
1
8
  ModelDefinition = function (model, config) {
2
9
  var sequences = {};
3
10
  var defaultAttributes = {};
@@ -6,36 +13,50 @@ ModelDefinition = function (model, config) {
6
13
  this.model = model;
7
14
 
8
15
  /**
9
- @param name model name like 'user' or named type like 'admin'
10
- @return boolean true if name is this definitions model or this definition
11
- contains a named model with that name
16
+ @param {String} name model name like 'user' or named type like 'admin'
17
+ @returns {Boolean} true if name is this definitions model or this definition
18
+ contains a named model with that name
12
19
  */
13
20
  this.matchesName = function (name) {
14
21
  return model == name || namedModels[name];
15
22
  }
16
23
 
24
+ // TODO
17
25
  this.merge = function (config) {
18
26
  }
19
27
 
20
28
  /**
21
- @param sequenceName
22
- @returns output of sequence function
29
+ Call the next method on the named sequence function
30
+
31
+ @param {String} sequenceName
32
+ @returns {String} output of sequence function
23
33
  */
24
34
  this.generate = function (sequenceName) {
25
- if (!sequences[sequenceName]) {
26
- throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+ model+"' definition")
35
+ var sequence = sequences[sequenceName];
36
+ if (!sequence) {
37
+ throw new MissingSequenceError("Can not find that sequence named [" + sequenceName + "] in '" + model + "' definition")
27
38
  }
28
- return sequences[sequenceName].next();
39
+ return sequence.next();
29
40
  }
30
41
 
42
+ /**
43
+ Build a fixture by name
44
+
45
+ @param {String} name fixture name
46
+ @param {Object} opts attributes to override
47
+ @returns {Object} json
48
+ */
31
49
  this.build = function (name, opts) {
32
50
  var modelAttributes = namedModels[name] || {};
51
+ // merge default, modelAttributes and opts to get the rough fixture
33
52
  var fixture = $.extend({}, defaultAttributes, modelAttributes, opts);
34
- for (attr in fixture) {
35
- if (typeof fixture[attr] == 'function') {
36
- fixture[attr] = fixture[attr].call(this)
53
+ // convert attributes that are functions to strings
54
+ for (attribute in fixture) {
55
+ if (typeof fixture[attribute] == 'function') {
56
+ fixture[attribute] = fixture[attribute].call(this, fixture);
37
57
  }
38
58
  }
59
+ // set the id, unless it was already set in opts
39
60
  if (!fixture.id) {
40
61
  fixture.id = modelId++;
41
62
  }
@@ -43,12 +64,12 @@ ModelDefinition = function (model, config) {
43
64
  }
44
65
 
45
66
  /**
46
- Build a list of fixtures
67
+ Build a list of fixtures
47
68
 
48
- @param name model name or named model type
49
- @param number of fixtures to build
50
- @param opts attribute options
51
- @returns array of fixtures
69
+ @param name model name or named model type
70
+ @param number of fixtures to build
71
+ @param opts attribute options
72
+ @returns array of fixtures
52
73
  */
53
74
  this.buildList = function (name, number, opts) {
54
75
  var arr = [];
@@ -58,8 +79,12 @@ ModelDefinition = function (model, config) {
58
79
  return arr;
59
80
  }
60
81
 
82
+ // Set the modelId back to 1, and reset the sequences
61
83
  this.reset = function () {
62
84
  modelId = 1;
85
+ for (name in sequences) {
86
+ sequences[name].reset();
87
+ }
63
88
  }
64
89
 
65
90
  var parseDefault = function (object) {
data/src/sequence.js CHANGED
@@ -1,6 +1,5 @@
1
1
  Sequence = function (fn) {
2
2
  var index = 1;
3
- var fn = fn;
4
3
 
5
4
  this.next = function () {
6
5
  return fn.call(this, index++);
@@ -9,8 +8,8 @@ Sequence = function (fn) {
9
8
  this.reset = function () {
10
9
  index = 1;
11
10
  }
12
- }
11
+ };
13
12
 
14
13
  function MissingSequenceError(message) {
15
14
  this.toString = function() { return message }
16
- }
15
+ };
data/src/store.js CHANGED
@@ -1,17 +1,19 @@
1
1
  DS.Store.reopen({
2
-
3
- usingFixtureAdapter: function() {
2
+ /**
3
+ @returns {Boolean} true if store's adapter is DS.FixtureAdapter
4
+ */
5
+ usingFixtureAdapter: function () {
4
6
  var adapter = this.adapterFor('application');
5
- return adapter instanceof DS.FixtureAdapter
7
+ return adapter instanceof DS.FixtureAdapter;
6
8
  },
7
9
 
8
10
  /**
9
- Make new fixture and save to store. If the store is using FixtureAdapter,
10
- will push to FIXTURE array, otherwise will use push method on adapter.
11
+ Make new fixture and save to store. If the store is using FixtureAdapter,
12
+ will push to FIXTURE array, otherwise will use push method on adapter.
11
13
 
12
- @param name name of fixture
13
- @param options fixture options
14
- @returns json or record
14
+ @param {String} name name of fixture
15
+ @param {Object} options fixture options
16
+ @returns {Object|DS.Model} json or record depending on the adapter type
15
17
  */
16
18
  makeFixture: function (name, options) {
17
19
  var modelName = FactoryGuy.lookupModelForName(name);
@@ -24,7 +26,7 @@ DS.Store.reopen({
24
26
  } else {
25
27
  var self = this;
26
28
  var model;
27
- Em.run( function() {
29
+ Em.run(function () {
28
30
  model = self.push(modelName, fixture);
29
31
  self.setBelongsToRESTAdapter(modelType, modelName, model);
30
32
  });
@@ -33,13 +35,13 @@ DS.Store.reopen({
33
35
  },
34
36
 
35
37
  /**
36
- Make a list of Fixtures
38
+ Make a list of Fixtures
37
39
 
38
- @param name name of fixture
39
- @param number number of fixtures
40
- @param options fixture options
41
- @returns list of json fixtures or records depending on the adapter type
42
- */
40
+ @param {String} name name of fixture
41
+ @param {Number} number number to create
42
+ @param {Object} options fixture options
43
+ @returns {Array} list of json fixtures or records depending on the adapter type
44
+ */
43
45
  makeList: function (name, number, options) {
44
46
  var arr = [];
45
47
  for (var i = 0; i < number; i++) {
@@ -49,16 +51,16 @@ DS.Store.reopen({
49
51
  },
50
52
 
51
53
  /**
52
- Set the belongsTo association for FixtureAdapter,
53
- with models that have a hasMany association.
54
+ Set the belongsTo association for FixtureAdapter,
55
+ with models that have a hasMany association.
54
56
 
55
- For example if a user hasMany projects, then set the user.id
56
- on each project that the user hasMany of, so that the project
57
- now has the belongsTo user association setup.
57
+ For example if a user hasMany projects, then set the user.id
58
+ on each project that the user hasMany of, so that the project
59
+ now has the belongsTo user association setup.
58
60
 
59
- @param modelType model type like App.User
60
- @param modelName model name like 'user'
61
- @param parentFixture parent to assign as belongTo
61
+ @param {String} modelType model type like App.User
62
+ @param {String} modelName model name like 'user'
63
+ @param {Object} parentFixture parent to assign as belongTo
62
64
  */
63
65
  setBelongsToFixturesAdapter: function (modelType, modelName, parentFixture) {
64
66
  var store = this;
@@ -68,7 +70,7 @@ DS.Store.reopen({
68
70
  relationShips.hasMany.forEach(function (relationship) {
69
71
  var hasManyModel = store.modelFor(Em.String.singularize(relationship));
70
72
  if (parentFixture[relationship]) {
71
- parentFixture[relationship].forEach(function(id) {
73
+ parentFixture[relationship].forEach(function (id) {
72
74
  var hasManyfixtures = adapter.fixturesForType(hasManyModel);
73
75
  var fixture = adapter.findFixtureById(hasManyfixtures, id);
74
76
  fixture[modelName] = parentFixture.id;
@@ -79,38 +81,59 @@ DS.Store.reopen({
79
81
  },
80
82
 
81
83
  /**
82
- Set the belongsTo association for the REST type models
83
- with a hasMany association
84
+ For the REST type models:
84
85
 
85
- For example if a user hasMany projects, then set the user
86
- on each project that the user hasMany of, so that the project
87
- now has the belongsTo user association setup
86
+ Set the belongsTo association with a hasMany association
88
87
 
89
- @param modelType model type like 'App.User'
90
- @param modelName model name like 'user'
91
- @param parent model to check for hasMany
88
+ Set this model in the parent hasMany array this model belongsTo
89
+
90
+ For example if a user hasMany projects, then set the user
91
+ on each project that the user hasMany of, so that the project
92
+ now has the belongsTo user association setup
93
+
94
+ @param {DS.Model} modelType model type like 'User'
95
+ @param {String} modelName model name like 'user'
96
+ @param {DS.Model} model
92
97
  */
93
- setBelongsToRESTAdapter: function (modelType, modelName, parent) {
94
- var relationShips = Ember.get(modelType, 'relationshipNames');
98
+ setBelongsToRESTAdapter: function (modelType, modelName, model) {
99
+ var self = this;
100
+ Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
101
+ if (relationship.kind == 'hasMany') {
102
+ var children = model.get(name) || [];
103
+ children.forEach(function (child) {
104
+ child.set(modelName, model)
105
+ })
106
+ }
107
+
108
+ if (relationship.kind == 'belongsTo') {
109
+ var belongsToRecord = model.get(name);
110
+ if (belongsToRecord) {
111
+ var hasManyName = self.findHasManyRelationshipName(belongsToRecord, model)
112
+ belongsToRecord.get(hasManyName).addObject(model);
113
+ }
114
+ }
115
+ })
116
+ },
95
117
 
96
- if (relationShips.hasMany) {
97
- relationShips.hasMany.forEach(function (name) {
98
- var children = parent.get(name);
99
- if (children.get('length') > 0) {
100
- children.forEach(function(child) {
101
- child.set(modelName, parent)
102
- })
118
+ findHasManyRelationshipName: function (belongToModel, childModel) {
119
+ var relationshipName;
120
+ Ember.get(belongToModel.constructor, 'relationshipsByName').forEach(
121
+ function (name, relationship) {
122
+ if (relationship.kind == 'hasMany' &&
123
+ relationship.type == childModel.constructor) {
124
+ relationshipName = relationship.key;
103
125
  }
104
- })
105
- }
126
+ }
127
+ )
128
+ return relationshipName;
106
129
  },
107
130
 
108
131
  /**
109
- Adding a pushPayload for FixtureAdapter, but using the original with
110
- other adapters that support pushPayload.
132
+ Adding a pushPayload for FixtureAdapter, but using the original with
133
+ other adapters that support pushPayload.
111
134
 
112
- @param type
113
- @param payload
135
+ @param {String} type
136
+ @param {Object} payload
114
137
  */
115
138
  pushPayload: function (type, payload) {
116
139
  if (this.usingFixtureAdapter()) {
@@ -126,34 +149,60 @@ DS.Store.reopen({
126
149
  DS.FixtureAdapter.reopen({
127
150
 
128
151
  /**
129
- Overriding createRecord in FixtureAdapter to add the record
130
- created to the hashMany records for all of the records that
131
- this one belongsTo.
132
-
133
- @method createRecord
134
- @param {DS.Store} store
135
- @param {subclass of DS.Model} type
136
- @param {DS.Model} record
137
- @return {Promise} promise
138
- */
139
- createRecord: function(store, type, record) {
152
+ Overriding createRecord to add the record created to the
153
+ hashMany records for all of the records that this record belongsTo.
154
+
155
+ For example:
156
+
157
+ If models are defined like so:
158
+
159
+ User = DS.Model.extend({
160
+ projects: DS.hasMany('project')
161
+ })
162
+
163
+ Project = DS.Model.extend({
164
+ user: DS.belongsTo('user')
165
+ })
166
+
167
+ and you create a project record with a user defined:
168
+ store.createRecord('project', {user: user})
169
+
170
+ this method will take the new project created and add it to the user's 'projects'
171
+ hasMany array.
172
+
173
+ And a full code example:
174
+
175
+ var userJson = store.makeFixture('user');
176
+
177
+ store.find('user', userJson.id).then(function(user) {
178
+ store.createRecord('project', {user: user}).save()
179
+ .then( function(project) {
180
+ // user.get('projects.length') == 1;
181
+ })
182
+ })
183
+
184
+ @method createRecord
185
+ @param {DS.Store} store
186
+ @param {subclass of DS.Model} type
187
+ @param {DS.Model} record
188
+ @return {Promise} promise
189
+ */
190
+ createRecord: function (store, type, record) {
140
191
  var promise = this._super(store, type, record);
141
192
 
142
- // promise.then( function() {
143
- // var hasManyName = Ember.String.pluralize(type.typeKey);
144
- // var relationShips = Ember.get(type, 'relationshipNames');
145
- // if (relationShips.belongsTo) {
146
- // console.log('record',record+'', type.typeKey, hasManyName);
147
- // relationShips.belongsTo.forEach(function (relationship) {
148
- // console.log(relationship, record.get(relationship)+'')
149
- // var belongsToRecord = record.get(relationship);
150
- // console.log(relationshipForType)
151
- // belongsToRecord.get(hasManyName).addObject(record);
152
- // })
153
- // }
154
- // })
193
+ promise.then(function () {
194
+ var relationShips = Ember.get(type, 'relationshipNames');
195
+ if (relationShips.belongsTo) {
196
+ relationShips.belongsTo.forEach(function (relationship) {
197
+ var belongsToRecord = record.get(relationship);
198
+ if (belongsToRecord) {
199
+ var hasManyName = store.findHasManyRelationshipName(belongsToRecord, record);
200
+ belongsToRecord.get(hasManyName).addObject(record);
201
+ }
202
+ })
203
+ }
204
+ });
205
+
155
206
  return promise;
156
207
  }
157
-
158
- })
159
-
208
+ })