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 +1 -0
- data/README.md +45 -26
- data/bower.json +1 -1
- data/dist/ember-data-factory-guy.js +247 -124
- data/dist/ember-data-factory-guy.min.js +1 -1
- data/ember-data-factory-guy.gemspec +1 -1
- data/package.json +2 -7
- data/src/factory_guy.js +56 -24
- data/src/factory_guy_test_mixin.js +26 -7
- data/src/model_definition.js +41 -16
- data/src/sequence.js +2 -3
- data/src/store.js +123 -74
- data/tests/active_model_adapter_factory_test.js +9 -2
- data/tests/factory_guy_test.js +28 -1
- data/tests/fixture_adapter_factory_test.js +15 -15
- data/tests/rest_adapter_factory_test.js +35 -1
- data/vendor/assets/javascripts/ember_data_factory_guy.js +247 -124
- metadata +2 -2
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
|
62
|
-
type: DS.attr
|
63
|
-
projects: DS.hasMany
|
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:
|
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
|
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: {
|
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
|
-
//
|
118
|
-
//
|
119
|
-
//
|
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
|
-
|
128
|
-
store.
|
129
|
-
|
130
|
-
|
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
|
-
//
|
168
|
+
// with store using => DS.ActiveModelAdapter/DS.RestAdapter
|
155
169
|
//
|
156
|
-
//
|
157
|
-
//
|
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: '
|
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,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
|
-
@
|
28
|
-
|
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
|
-
|
39
|
-
|
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
|
-
|
43
|
-
|
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
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
83
|
+
Build a list of fixtures
|
64
84
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
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('
|
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 '
|
175
|
-
|
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 '
|
190
|
-
|
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
|
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
|
-
|
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
|
-
|
293
|
-
|
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
|
-
|
296
|
-
|
297
|
-
|
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(
|
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
|
-
|
377
|
+
Make a list of Fixtures
|
320
378
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
336
|
-
|
393
|
+
Set the belongsTo association for FixtureAdapter,
|
394
|
+
with models that have a hasMany association.
|
337
395
|
|
338
|
-
|
339
|
-
|
340
|
-
|
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
|
-
|
343
|
-
|
344
|
-
|
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
|
-
|
366
|
-
|
423
|
+
For the REST type models:
|
424
|
+
|
425
|
+
Set the belongsTo association with a hasMany association
|
367
426
|
|
368
|
-
|
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
|
-
|
373
|
-
|
374
|
-
|
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,
|
377
|
-
var
|
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
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
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
|
-
|
393
|
-
|
471
|
+
Adding a pushPayload for FixtureAdapter, but using the original with
|
472
|
+
other adapters that support pushPayload.
|
394
473
|
|
395
|
-
|
396
|
-
|
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
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
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
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
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
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
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.
|
622
|
+
this.buildAjaxCreateResponse(name, opts),
|
505
623
|
{type: 'POST'}
|
506
624
|
)
|
507
625
|
},
|
508
626
|
|
509
|
-
|
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
|
})
|