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.
data/Gruntfile.js CHANGED
@@ -56,6 +56,7 @@ module.exports = function(grunt) {
56
56
  grunt.loadNpmTasks('grunt-contrib-concat');
57
57
  grunt.loadNpmTasks('grunt-contrib-uglify');
58
58
  grunt.loadNpmTasks('grunt-contrib-qunit');
59
+ grunt.loadNpmTasks('grunt-bump');
59
60
 
60
61
  grunt.registerTask('default', ['concat', 'uglify']);
61
62
  grunt.registerTask('test', ['concat:dist', 'qunit']);
data/README.md CHANGED
@@ -17,6 +17,13 @@ then:
17
17
  $ bundle install
18
18
  ```
19
19
 
20
+ then:
21
+
22
+ ```javascript
23
+ // require the 'ember_data_factory_guy' javascript file in your test helper
24
+ //= require ember_data_factory_guy
25
+ ```
26
+
20
27
  # Using as bower component
21
28
 
22
29
  Add as one of your dependencies in bower.json file:
@@ -58,13 +65,14 @@ but BEFORE you require your models.
58
65
  // Model definitions
59
66
 
60
67
  User = DS.Model.extend({
61
- name: DS.attr 'string',
62
- type: DS.attr 'string',
63
- projects: DS.hasMany 'project'
68
+ name: DS.attr('string'),
69
+ type: DS.attr('string'),
70
+ projects: DS.hasMany('project')
64
71
  })
65
72
 
66
73
  Project = DS.Model.extend({
67
- title: DS.attr 'string'
74
+ title: DS.attr('string')
75
+ user: DS.belongsTo('user')
68
76
  })
69
77
 
70
78
  ////////////////////////////////////////////
@@ -77,12 +85,13 @@ but BEFORE you require your models.
77
85
  }
78
86
  },
79
87
 
80
- // default values for 'user' attributes
88
+ // default 'user' attributes
81
89
  default: {
82
90
  type: 'normal',
83
91
  // use the 'userName' sequence for this attribute
84
92
  name: FactoryGuy.generate('userName')
85
93
  },
94
+
86
95
  // named 'user' type with custom attributes
87
96
  admin: {
88
97
  type: 'superuser',
@@ -91,13 +100,16 @@ but BEFORE you require your models.
91
100
  });
92
101
 
93
102
  FactoryGuy.define('project', {
94
- default: {title: 'Project'}
103
+ default: {
104
+ title: 'Project'
105
+ }
95
106
  });
96
107
 
97
108
  //////////////////////////////////////////////////////////////////
98
109
  // ** Make one fixture at time **
99
110
  // building json with FactoryGuy.build
100
111
  //
112
+
101
113
  var userJson = FactoryGuy.build('user') // {id: 1, name: 'User1', type: 'normal'}
102
114
  // note the sequence used in the name attribute
103
115
  var user2Json = FactoryGuy.build('user') // {id: 2, name: 'User2', type: 'normal'}
@@ -108,26 +120,29 @@ but BEFORE you require your models.
108
120
  // ** Make a list of fixtures **
109
121
  // building json with FactoryGuy.buildList
110
122
  //
123
+
111
124
  var userJson = FactoryGuy.buildList('user',2) // [ {id: 1, name: 'User1', type: 'normal'}, {id: 2, name: 'User2', type: 'normal'} ]
112
125
 
113
126
  //////////////////////////////////////////////////////////////////
114
- // store.makeFixture method creates model in the store
115
- // store.makeList method creates list of models in the store
116
127
  //
117
- // with DS.Fixture adapter
118
- // makeFixture returns json
119
- // makeList returns json
128
+ // with store using => DS.Fixture adapter
129
+ //
130
+ // store.makeFixture => creates model in the store and returns json
131
+ // store.makeList => creates list of models in the store and returns json
120
132
  //
121
- store.makeFixture('user'); // user.FIXTURES = {id: 1, name: 'User1', type: 'normal'}
122
- store.makeFixture('user', {name: 'bob'}); // user.FIXTURES = {id: 2, name: 'bob', type: 'normal'}
123
- store.makeFixture('admin'); // user.FIXTURES = {id: 3, name: 'Admin', type: 'superuser'}
124
- store.makeFixture('admin', name: 'My name'); // user.FIXTURES = {id: 4, name: 'My name', type: 'normal'}
125
133
 
134
+ store.makeFixture('user'); // user.FIXTURES = [{id: 1, name: 'User1', type: 'normal'}]
135
+ store.makeFixture('user', {name: 'bob'}); // user.FIXTURES = [{id: 2, name: 'bob', type: 'normal'}]
136
+ store.makeFixture('admin'); // user.FIXTURES = [{id: 3, name: 'Admin', type: 'superuser'}]
137
+ store.makeFixture('admin', name: 'Fred'); // user.FIXTURES = [{id: 4, name: 'Fred', type: 'superuser'}]
126
138
 
127
- // Use store.find to get the model instance
128
- store.makeFixture('user');
129
- store.find('user', 1).then(function(user) {
130
- user.get('name') == 'My name';
139
+
140
+ // Use store.find to get the model instance ( Remember this is the Fixture adapter, if
141
+ // you use the ActiveModelAdapter or RESTAdapter the record is returned so you don't
142
+ // have to then go and find it
143
+ var userJson = store.makeFixture('user');
144
+ store.find('user', userJson.id).then(function(user) {
145
+ user.toJSON() ( has all the same key/values as ) userJson;
131
146
  });
132
147
 
133
148
  // and to setup associations ...
@@ -147,21 +162,24 @@ but BEFORE you require your models.
147
162
  });
148
163
  });
149
164
 
165
+
150
166
  //////////////////////////////////////////////////////////////////
151
- // store.makeFixture method creates model and adds it to store
152
- // store.makeList methods creates list of models and ads each to the store
153
167
  //
154
- // with DS.ActiveModelAdapter/DS.RestAdapter
168
+ // with store using => DS.ActiveModelAdapter/DS.RestAdapter
155
169
  //
156
- // returns a model instances so you can synchronously
157
- // start asking for data, as soon as you get the model
170
+ // store.makeFixture => creates model in the store and returns model instance
171
+ // store.makeList => creates list of models in the store and returns model instance
158
172
  //
173
+ // *NOTE* since you are now getting a model instances, you can synchronously
174
+ // start asking for data from the model
175
+ //
176
+
159
177
  var user = store.makeFixture('user'); // user.toJSON() = {id: 1, name: 'User1', type: 'normal'}
160
178
  // note that the user name is a sequence
161
179
  var user = store.makeFixture('user'); // user.toJSON() = {id: 2, name: 'User2', type: 'normal'}
162
180
  var user = store.makeFixture('user', {name: 'bob'}); // user.toJSON() = {id: 3, name: 'bob', type: 'normal'}
163
181
  var user = store.makeFixture('admin'); // user.toJSON() = {id: 4, name: 'Admin', type: 'superuser'}
164
- var user = store.makeFixture('admin', name: 'Nother Admin'); // user.toJSON() = {id: 5, name: 'Nother Admin', type: 'superuser'}
182
+ var user = store.makeFixture('admin', name: 'Fred'); // user.toJSON() = {id: 5, name: 'Fred', type: 'superuser'}
165
183
 
166
184
  // and to setup associations ...
167
185
 
@@ -214,12 +232,13 @@ test("make a user using fixture adapter", function() {
214
232
  testHelper.useFixtureAdapter();
215
233
  var json = make('user');
216
234
  equal(User.FIXTURES.length, 1);
235
+ equal(User.FIXTURES[0], json);
217
236
  });
218
237
 
219
238
  // assuming your default adapter is ActiveModelAdapter or RESTAdapter
220
239
  test("make a user using your applications default adapter", function() {
221
240
  var user = make('user');
222
- equal(store.all('user').get('content.length'), 1)
241
+ equal(store.all('user').get('content.length'), 1);
223
242
  equal(user instanceof DS.Model, true);
224
243
  });
225
244
 
data/bower.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>"
@@ -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,12 +8,19 @@ 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
+ };
16
+
17
+ /**
18
+ A ModelDefinition encapsulates a model's definition
17
19
 
20
+ @param model
21
+ @param config
22
+ @constructor
23
+ */
18
24
  ModelDefinition = function (model, config) {
19
25
  var sequences = {};
20
26
  var defaultAttributes = {};
@@ -23,36 +29,50 @@ ModelDefinition = function (model, config) {
23
29
  this.model = model;
24
30
 
25
31
  /**
26
- @param name model name like 'user' or named type like 'admin'
27
- @return boolean true if name is this definitions model or this definition
28
- contains a named model with that name
32
+ @param {String} name model name like 'user' or named type like 'admin'
33
+ @returns {Boolean} true if name is this definitions model or this definition
34
+ contains a named model with that name
29
35
  */
30
36
  this.matchesName = function (name) {
31
37
  return model == name || namedModels[name];
32
38
  }
33
39
 
40
+ // TODO
34
41
  this.merge = function (config) {
35
42
  }
36
43
 
37
44
  /**
38
- @param sequenceName
39
- @returns output of sequence function
45
+ Call the next method on the named sequence function
46
+
47
+ @param {String} sequenceName
48
+ @returns {String} output of sequence function
40
49
  */
41
50
  this.generate = function (sequenceName) {
42
- if (!sequences[sequenceName]) {
43
- throw new MissingSequenceError("Can not find that sequence named ["+sequenceName+"] in '"+ model+"' definition")
51
+ var sequence = sequences[sequenceName];
52
+ if (!sequence) {
53
+ throw new MissingSequenceError("Can not find that sequence named [" + sequenceName + "] in '" + model + "' definition")
44
54
  }
45
- return sequences[sequenceName].next();
55
+ return sequence.next();
46
56
  }
47
57
 
58
+ /**
59
+ Build a fixture by name
60
+
61
+ @param {String} name fixture name
62
+ @param {Object} opts attributes to override
63
+ @returns {Object} json
64
+ */
48
65
  this.build = function (name, opts) {
49
66
  var modelAttributes = namedModels[name] || {};
67
+ // merge default, modelAttributes and opts to get the rough fixture
50
68
  var fixture = $.extend({}, defaultAttributes, modelAttributes, opts);
51
- for (attr in fixture) {
52
- if (typeof fixture[attr] == 'function') {
53
- fixture[attr] = fixture[attr].call(this)
69
+ // convert attributes that are functions to strings
70
+ for (attribute in fixture) {
71
+ if (typeof fixture[attribute] == 'function') {
72
+ fixture[attribute] = fixture[attribute].call(this, fixture);
54
73
  }
55
74
  }
75
+ // set the id, unless it was already set in opts
56
76
  if (!fixture.id) {
57
77
  fixture.id = modelId++;
58
78
  }
@@ -60,12 +80,12 @@ ModelDefinition = function (model, config) {
60
80
  }
61
81
 
62
82
  /**
63
- Build a list of fixtures
83
+ Build a list of fixtures
64
84
 
65
- @param name model name or named model type
66
- @param number of fixtures to build
67
- @param opts attribute options
68
- @returns array of fixtures
85
+ @param name model name or named model type
86
+ @param number of fixtures to build
87
+ @param opts attribute options
88
+ @returns array of fixtures
69
89
  */
70
90
  this.buildList = function (name, number, opts) {
71
91
  var arr = [];
@@ -75,8 +95,12 @@ ModelDefinition = function (model, config) {
75
95
  return arr;
76
96
  }
77
97
 
98
+ // Set the modelId back to 1, and reset the sequences
78
99
  this.reset = function () {
79
100
  modelId = 1;
101
+ for (name in sequences) {
102
+ sequences[name].reset();
103
+ }
80
104
  }
81
105
 
82
106
  var parseDefault = function (object) {
@@ -144,12 +168,12 @@ FactoryGuy = {
144
168
 
145
169
  ```
146
170
 
147
- For the Person model, you can define fixtures like 'dude' or just use 'person'
148
- and get default values.
171
+ For the Person model, you can define named fixtures like 'dude' or
172
+ just use 'person' and get default values.
149
173
 
150
174
  And to get those fixtures you would call them this way:
151
175
 
152
- FactoryGuy.build('person') or FactoryGuy.build('dude')
176
+ FactoryGuy.build('dude') or FactoryGuy.build('person')
153
177
 
154
178
  @param model the model to define
155
179
  @param config your model definition object
@@ -162,18 +186,41 @@ FactoryGuy = {
162
186
  }
163
187
  },
164
188
 
189
+ /**
190
+ Used in model definitions to declare use of a sequence. For example:
191
+
192
+ ```
193
+
194
+ FactoryGuy.define('person', {
195
+ sequences: {
196
+ personName: function(num) {
197
+ return 'person #' + num;
198
+ }
199
+ },
200
+ default: {
201
+ name: FactoryGuy.generate('personName')
202
+ }
203
+ });
204
+
205
+ ```
206
+
207
+ @param {String} sequenceName
208
+ @returns {Function} wrapper function that is called by the model
209
+ definition containing the sequence
210
+ */
165
211
  generate: function (sequenceName) {
166
212
  return function () {
167
213
  return this.generate(sequenceName);
168
214
  }
169
215
  },
170
216
 
171
-
172
217
  /**
218
+ Given a name like 'person' or 'dude' determine what model this name
219
+ refers to. In this case it's 'person' for each one.
173
220
 
174
- @param name fixture name could be model name like 'user'
175
- or specific user like 'admin'
176
- @returns model associated with fixture name
221
+ @param {String} name a fixture name could be model name like 'person'
222
+ or a named person in model definition like 'dude'
223
+ @returns {String} model name associated with fixture name
177
224
  */
178
225
  lookupModelForName: function (name) {
179
226
  for (model in this.modelDefinitions) {
@@ -186,9 +233,9 @@ FactoryGuy = {
186
233
 
187
234
  /**
188
235
 
189
- @param name fixture name could be model name like 'user'
190
- or specific user like 'admin'
191
- @returns definition associated with model
236
+ @param {String} name a fixture name could be model name like 'person'
237
+ or a named person in model definition like 'dude'
238
+ @returns {ModelDefinition} definition associated with model
192
239
  */
193
240
  lookupDefinitionForName: function (name) {
194
241
  for (model in this.modelDefinitions) {
@@ -206,9 +253,9 @@ FactoryGuy = {
206
253
  FactoryGuy.build('user') for User model
207
254
  FactoryGuy.build('bob') for User model with bob attributes
208
255
 
209
- @param name fixture name
210
- @param opts options that will override default fixture values
211
- @returns {*}
256
+ @param {String} name fixture name
257
+ @param {Object} opts options that will override default fixture values
258
+ @returns {Object} json fixture
212
259
  */
213
260
  build: function (name, opts) {
214
261
  var definition = this.lookupDefinitionForName(name);
@@ -224,10 +271,10 @@ FactoryGuy = {
224
271
  FactoryGuy.buildList('user', 2) for 2 User models
225
272
  FactoryGuy.build('bob', 2) for 2 User model with bob attributes
226
273
 
227
- @param name fixture name
228
- @param number number of fixtures to create
229
- @param opts options that will override default fixture values
230
- @returns list of fixtures
274
+ @param {String} name fixture name
275
+ @param {Number} number number of fixtures to create
276
+ @param {Object} opts options that will override default fixture values
277
+ @returns {Array} list of fixtures
231
278
  */
232
279
  buildList: function (name, number, opts) {
233
280
  var definition = this.lookupDefinitionForName(name);
@@ -238,9 +285,11 @@ FactoryGuy = {
238
285
  },
239
286
 
240
287
  /**
288
+ TODO: This is kind of problematic right now .. needs work
289
+
241
290
  Clear model instances from FIXTURES array, and from store cache.
242
291
  Reset the id sequence for the models back to zero.
243
- */
292
+ */
244
293
  resetModels: function (store) {
245
294
  var typeMaps = store.typeMaps;
246
295
  for (model in this.modelDefinitions) {
@@ -259,9 +308,6 @@ FactoryGuy = {
259
308
  // store.unloadAll(typeMaps[model].type);
260
309
  // }
261
310
  // }
262
-
263
- // for (model in this.modelDefinitions) {
264
- // this.modelDefinitions[model].reset();
265
311
  }
266
312
  },
267
313
 
@@ -269,9 +315,9 @@ FactoryGuy = {
269
315
  Push fixture to model's FIXTURES array.
270
316
  Used when store's adapter is a DS.FixtureAdapter.
271
317
 
272
- @param modelClass DS.Model type
273
- @param fixture the fixture to add
274
- @returns json fixture data
318
+ @param {DS.Model} modelClass
319
+ @param {Object} fixture the fixture to add
320
+ @returns {Object} json fixture data
275
321
  */
276
322
  pushFixture: function (modelClass, fixture) {
277
323
  if (!modelClass['FIXTURES']) {
@@ -279,22 +325,34 @@ FactoryGuy = {
279
325
  }
280
326
  modelClass['FIXTURES'].push(fixture);
281
327
  return fixture;
328
+ },
329
+
330
+ /**
331
+ Clears all model definitions
332
+ */
333
+ clear: function (opts) {
334
+ if (!opts) {
335
+ this.modelDefinitions = {};
336
+ return;
337
+ }
282
338
  }
283
339
  }
284
340
  DS.Store.reopen({
285
-
286
- usingFixtureAdapter: function() {
341
+ /**
342
+ @returns {Boolean} true if store's adapter is DS.FixtureAdapter
343
+ */
344
+ usingFixtureAdapter: function () {
287
345
  var adapter = this.adapterFor('application');
288
- return adapter instanceof DS.FixtureAdapter
346
+ return adapter instanceof DS.FixtureAdapter;
289
347
  },
290
348
 
291
349
  /**
292
- Make new fixture and save to store. If the store is using FixtureAdapter,
293
- will push to FIXTURE array, otherwise will use push method on adapter.
350
+ Make new fixture and save to store. If the store is using FixtureAdapter,
351
+ will push to FIXTURE array, otherwise will use push method on adapter.
294
352
 
295
- @param name name of fixture
296
- @param options fixture options
297
- @returns json or record
353
+ @param {String} name name of fixture
354
+ @param {Object} options fixture options
355
+ @returns {Object|DS.Model} json or record depending on the adapter type
298
356
  */
299
357
  makeFixture: function (name, options) {
300
358
  var modelName = FactoryGuy.lookupModelForName(name);
@@ -307,7 +365,7 @@ DS.Store.reopen({
307
365
  } else {
308
366
  var self = this;
309
367
  var model;
310
- Em.run( function() {
368
+ Em.run(function () {
311
369
  model = self.push(modelName, fixture);
312
370
  self.setBelongsToRESTAdapter(modelType, modelName, model);
313
371
  });
@@ -316,13 +374,13 @@ DS.Store.reopen({
316
374
  },
317
375
 
318
376
  /**
319
- Make a list of Fixtures
377
+ Make a list of Fixtures
320
378
 
321
- @param name name of fixture
322
- @param number number of fixtures
323
- @param options fixture options
324
- @returns list of json fixtures or records depending on the adapter type
325
- */
379
+ @param {String} name name of fixture
380
+ @param {Number} number number to create
381
+ @param {Object} options fixture options
382
+ @returns {Array} list of json fixtures or records depending on the adapter type
383
+ */
326
384
  makeList: function (name, number, options) {
327
385
  var arr = [];
328
386
  for (var i = 0; i < number; i++) {
@@ -332,16 +390,16 @@ DS.Store.reopen({
332
390
  },
333
391
 
334
392
  /**
335
- Set the belongsTo association for FixtureAdapter,
336
- with models that have a hasMany association.
393
+ Set the belongsTo association for FixtureAdapter,
394
+ with models that have a hasMany association.
337
395
 
338
- For example if a user hasMany projects, then set the user.id
339
- on each project that the user hasMany of, so that the project
340
- now has the belongsTo user association setup.
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.
341
399
 
342
- @param modelType model type like App.User
343
- @param modelName model name like 'user'
344
- @param parentFixture parent to assign as belongTo
400
+ @param {String} modelType model type like App.User
401
+ @param {String} modelName model name like 'user'
402
+ @param {Object} parentFixture parent to assign as belongTo
345
403
  */
346
404
  setBelongsToFixturesAdapter: function (modelType, modelName, parentFixture) {
347
405
  var store = this;
@@ -351,7 +409,7 @@ DS.Store.reopen({
351
409
  relationShips.hasMany.forEach(function (relationship) {
352
410
  var hasManyModel = store.modelFor(Em.String.singularize(relationship));
353
411
  if (parentFixture[relationship]) {
354
- parentFixture[relationship].forEach(function(id) {
412
+ parentFixture[relationship].forEach(function (id) {
355
413
  var hasManyfixtures = adapter.fixturesForType(hasManyModel);
356
414
  var fixture = adapter.findFixtureById(hasManyfixtures, id);
357
415
  fixture[modelName] = parentFixture.id;
@@ -362,38 +420,59 @@ DS.Store.reopen({
362
420
  },
363
421
 
364
422
  /**
365
- Set the belongsTo association for the REST type models
366
- with a hasMany association
423
+ For the REST type models:
424
+
425
+ Set the belongsTo association with a hasMany association
367
426
 
368
- For example if a user hasMany projects, then set the user
369
- on each project that the user hasMany of, so that the project
370
- now has the belongsTo user association setup
427
+ Set this model in the parent hasMany array this model belongsTo
371
428
 
372
- @param modelType model type like 'App.User'
373
- @param modelName model name like 'user'
374
- @param parent model to check for hasMany
429
+ For example if a user hasMany projects, then set the user
430
+ on each project that the user hasMany of, so that the project
431
+ now has the belongsTo user association setup
432
+
433
+ @param {DS.Model} modelType model type like 'User'
434
+ @param {String} modelName model name like 'user'
435
+ @param {DS.Model} model
375
436
  */
376
- setBelongsToRESTAdapter: function (modelType, modelName, parent) {
377
- var relationShips = Ember.get(modelType, 'relationshipNames');
437
+ setBelongsToRESTAdapter: function (modelType, modelName, model) {
438
+ var self = this;
439
+ Ember.get(modelType, 'relationshipsByName').forEach(function (name, relationship) {
440
+ if (relationship.kind == 'hasMany') {
441
+ var children = model.get(name) || [];
442
+ children.forEach(function (child) {
443
+ child.set(modelName, model)
444
+ })
445
+ }
378
446
 
379
- if (relationShips.hasMany) {
380
- relationShips.hasMany.forEach(function (name) {
381
- var children = parent.get(name);
382
- if (children.get('length') > 0) {
383
- children.forEach(function(child) {
384
- child.set(modelName, parent)
385
- })
447
+ if (relationship.kind == 'belongsTo') {
448
+ var belongsToRecord = model.get(name);
449
+ if (belongsToRecord) {
450
+ var hasManyName = self.findHasManyRelationshipName(belongsToRecord, model)
451
+ belongsToRecord.get(hasManyName).addObject(model);
386
452
  }
387
- })
388
- }
453
+ }
454
+ })
455
+ },
456
+
457
+ findHasManyRelationshipName: function (belongToModel, childModel) {
458
+ var relationshipName;
459
+ Ember.get(belongToModel.constructor, 'relationshipsByName').forEach(
460
+ function (name, relationship) {
461
+ if (relationship.kind == 'hasMany' &&
462
+ relationship.type == childModel.constructor) {
463
+ relationshipName = relationship.key;
464
+ }
465
+ }
466
+ )
467
+ return relationshipName;
389
468
  },
390
469
 
391
470
  /**
392
- Adding a pushPayload for FixtureAdapter, but using the original with
393
- other adapters that support pushPayload.
471
+ Adding a pushPayload for FixtureAdapter, but using the original with
472
+ other adapters that support pushPayload.
394
473
 
395
- @param type
396
- @param payload
474
+ @param {String} type
475
+ @param {Object} payload
397
476
  */
398
477
  pushPayload: function (type, payload) {
399
478
  if (this.usingFixtureAdapter()) {
@@ -409,38 +488,63 @@ DS.Store.reopen({
409
488
  DS.FixtureAdapter.reopen({
410
489
 
411
490
  /**
412
- Overriding createRecord in FixtureAdapter to add the record
413
- created to the hashMany records for all of the records that
414
- this one belongsTo.
415
-
416
- @method createRecord
417
- @param {DS.Store} store
418
- @param {subclass of DS.Model} type
419
- @param {DS.Model} record
420
- @return {Promise} promise
421
- */
422
- createRecord: function(store, type, record) {
491
+ Overriding createRecord to add the record created to the
492
+ hashMany records for all of the records that this record belongsTo.
493
+
494
+ For example:
495
+
496
+ If models are defined like so:
497
+
498
+ User = DS.Model.extend({
499
+ projects: DS.hasMany('project')
500
+ })
501
+
502
+ Project = DS.Model.extend({
503
+ user: DS.belongsTo('user')
504
+ })
505
+
506
+ and you create a project record with a user defined:
507
+ store.createRecord('project', {user: user})
508
+
509
+ this method will take the new project created and add it to the user's 'projects'
510
+ hasMany array.
511
+
512
+ And a full code example:
513
+
514
+ var userJson = store.makeFixture('user');
515
+
516
+ store.find('user', userJson.id).then(function(user) {
517
+ store.createRecord('project', {user: user}).save()
518
+ .then( function(project) {
519
+ // user.get('projects.length') == 1;
520
+ })
521
+ })
522
+
523
+ @method createRecord
524
+ @param {DS.Store} store
525
+ @param {subclass of DS.Model} type
526
+ @param {DS.Model} record
527
+ @return {Promise} promise
528
+ */
529
+ createRecord: function (store, type, record) {
423
530
  var promise = this._super(store, type, record);
424
531
 
425
- // promise.then( function() {
426
- // var hasManyName = Ember.String.pluralize(type.typeKey);
427
- // var relationShips = Ember.get(type, 'relationshipNames');
428
- // if (relationShips.belongsTo) {
429
- // console.log('record',record+'', type.typeKey, hasManyName);
430
- // relationShips.belongsTo.forEach(function (relationship) {
431
- // console.log(relationship, record.get(relationship)+'')
432
- // var belongsToRecord = record.get(relationship);
433
- // console.log(relationshipForType)
434
- // belongsToRecord.get(hasManyName).addObject(record);
435
- // })
436
- // }
437
- // })
532
+ promise.then(function () {
533
+ var relationShips = Ember.get(type, 'relationshipNames');
534
+ if (relationShips.belongsTo) {
535
+ relationShips.belongsTo.forEach(function (relationship) {
536
+ var belongsToRecord = record.get(relationship);
537
+ if (belongsToRecord) {
538
+ var hasManyName = store.findHasManyRelationshipName(belongsToRecord, record);
539
+ belongsToRecord.get(hasManyName).addObject(record);
540
+ }
541
+ })
542
+ }
543
+ });
544
+
438
545
  return promise;
439
546
  }
440
-
441
547
  })
442
-
443
-
444
548
  FactoryGuyTestMixin = Em.Mixin.create({
445
549
 
446
550
  // Pass in the app root, which typically is App.
@@ -454,6 +558,13 @@ FactoryGuyTestMixin = Em.Mixin.create({
454
558
  this.getStore().adapterFor('application').simulateRemoteResponse = false;
455
559
  },
456
560
 
561
+ /**
562
+ Proxy to store's find method
563
+
564
+ @param {String or subclass of DS.Model} type
565
+ @param {Object|String|Integer|null} id
566
+ @return {Promise} promise
567
+ */
457
568
  find: function(type, id) {
458
569
  return this.getStore().find(type, id);
459
570
  },
@@ -474,6 +585,13 @@ FactoryGuyTestMixin = Em.Mixin.create({
474
585
  return this.getStore().push(type, hash);
475
586
  },
476
587
 
588
+ /**
589
+ Using mockjax to stub an http request.
590
+
591
+ @param {String} url request url
592
+ @param {Object} json response
593
+ @param {Object} options ajax request options
594
+ */
477
595
  stubEndpointForHttpRequest: function (url, json, options) {
478
596
  options = options || {};
479
597
  var request = {
@@ -492,21 +610,27 @@ FactoryGuyTestMixin = Em.Mixin.create({
492
610
  },
493
611
 
494
612
  /**
495
- * Handling ajax POST for a model
496
- *
497
- * @param name of the fixture ( or model ) to create
498
- * @param opts fixture options
613
+ Handling ajax POST ( create record ) for a model
614
+
615
+ @param {String} name of the fixture ( or model ) to create
616
+ @param {Object} opts fixture options
499
617
  */
500
618
  handleCreate: function (name, opts) {
501
619
  var model = FactoryGuy.lookupModelForName(name);
502
620
  this.stubEndpointForHttpRequest(
503
621
  "/" + Em.String.pluralize(model),
504
- this.buildAjaxResponse(name, opts),
622
+ this.buildAjaxCreateResponse(name, opts),
505
623
  {type: 'POST'}
506
624
  )
507
625
  },
508
626
 
509
- buildAjaxResponse: function (name, opts) {
627
+ /**
628
+ Build the json used for creating record
629
+
630
+ @param {String} name of the fixture ( or model ) to create
631
+ @param {Object} opts fixture options
632
+ ¬ */
633
+ buildAjaxCreateResponse: function (name, opts) {
510
634
  var fixture = FactoryGuy.build(name, opts);
511
635
  var model = FactoryGuy.lookupModelForName(name);
512
636
  var hash = {};
@@ -529,5 +653,4 @@ FactoryGuyTestMixin = Em.Mixin.create({
529
653
  teardown: function () {
530
654
  FactoryGuy.resetModels(this.getStore());
531
655
  }
532
-
533
656
  })