ember-data-factory-guy 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ })