ember-data-source 1.0.0.beta.6 → 1.0.0.beta.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a906bfbb598d2bf2f3c6aa62f7f7ff61bdfb5e9
4
- data.tar.gz: bc0c8336a35549e053eae512cdb53f42829f8e8d
3
+ metadata.gz: c30d9bd2bffbba3064ced349b8b257a36ae7bdc3
4
+ data.tar.gz: 870dc095c98df02b8721d66630a6fa3adfa64b2b
5
5
  SHA512:
6
- metadata.gz: a8250a2041b0b784b64137378a04bef053b7f829fbbcc3a83a1467158dc5c16c4fd3fb9a1c7ab6813762cfa1718e5bb94e716bbd3e07fa43b0d79db6c5e44f7e
7
- data.tar.gz: 0ab5b1e6106504e3af4c0a80530f0c8dbe8dc0ff2b1aef664b8d171bdc0a1c87f74e892ef3d8b1a8578840bd165ee5731fe8741944c9406dafca2cb14c1e9419
6
+ metadata.gz: ddb4fa73c9ac26136586734172f11fa46216a244e2722c18a9cb33718e2af16a37fa90492a7f1a5bc218a26b07b7d25729f9099345bb82005eb01424a38e106f
7
+ data.tar.gz: 33b783baf1246054e597ec3b6f9f0f7d683436f3dcc4d7d9637ef965e91352d0d2d2a4945ddff1d019d69b4797d9d634e98241c7142b3aa0c082ffe3c5c4cbd7
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0-beta.6
1
+ 1.0.0-beta.7
data/dist/ember-data.js CHANGED
@@ -3,12 +3,10 @@
3
3
  * @copyright Copyright 2011-2014 Tilde Inc. and contributors.
4
4
  * Portions Copyright 2011 LivingSocial Inc.
5
5
  * @license Licensed under MIT license (see license.js)
6
- * @version 1.0.0-beta.6
6
+ * @version 1.0.0-beta.7+canary.f482da04
7
7
  */
8
-
9
-
10
- (function() {
11
- var define, requireModule;
8
+ (function(global) {
9
+ var define, requireModule, require, requirejs;
12
10
 
13
11
  (function() {
14
12
  var registry = {}, seen = {};
@@ -17,10604 +15,11118 @@ var define, requireModule;
17
15
  registry[name] = { deps: deps, callback: callback };
18
16
  };
19
17
 
20
- requireModule = function(name) {
18
+ requirejs = require = requireModule = function(name) {
19
+ requirejs._eak_seen = registry;
20
+
21
21
  if (seen[name]) { return seen[name]; }
22
22
  seen[name] = {};
23
23
 
24
- var mod, deps, callback, reified , exports;
25
-
26
- mod = registry[name];
27
-
28
- if (!mod) {
29
- throw new Error("Module '" + name + "' not found.");
24
+ if (!registry[name]) {
25
+ throw new Error("Could not find module " + name);
30
26
  }
31
27
 
32
- deps = mod.deps;
33
- callback = mod.callback;
34
- reified = [];
35
- exports;
28
+ var mod = registry[name],
29
+ deps = mod.deps,
30
+ callback = mod.callback,
31
+ reified = [],
32
+ exports;
36
33
 
37
34
  for (var i=0, l=deps.length; i<l; i++) {
38
35
  if (deps[i] === 'exports') {
39
36
  reified.push(exports = {});
40
37
  } else {
41
- reified.push(requireModule(deps[i]));
38
+ reified.push(requireModule(resolve(deps[i])));
42
39
  }
43
40
  }
44
41
 
45
42
  var value = callback.apply(this, reified);
46
43
  return seen[name] = exports || value;
44
+
45
+ function resolve(child) {
46
+ if (child.charAt(0) !== '.') { return child; }
47
+ var parts = child.split("/");
48
+ var parentBase = name.split("/").slice(0, -1);
49
+
50
+ for (var i=0, l=parts.length; i<l; i++) {
51
+ var part = parts[i];
52
+
53
+ if (part === '..') { parentBase.pop(); }
54
+ else if (part === '.') { continue; }
55
+ else { parentBase.push(part); }
56
+ }
57
+
58
+ return parentBase.join("/");
59
+ }
47
60
  };
48
61
  })();
49
- (function() {
50
- /**
51
- @module ember-data
52
- */
53
-
54
- /**
55
- All Ember Data methods and functions are defined inside of this namespace.
56
-
57
- @class DS
58
- @static
59
- */
60
- var DS;
61
- if ('undefined' === typeof DS) {
62
- /**
63
- @property VERSION
64
- @type String
65
- @default '1.0.0-beta.6'
66
- @static
67
- */
68
- DS = Ember.Namespace.create({
69
- VERSION: '1.0.0-beta.6'
62
+
63
+ define("activemodel-adapter/lib/initializers",
64
+ ["../../ember-data/lib/system/container_proxy","./system/active_model_serializer","./system/active_model_adapter"],
65
+ function(__dependency1__, __dependency2__, __dependency3__) {
66
+ "use strict";
67
+ var ContainerProxy = __dependency1__["default"];
68
+ var ActiveModelSerializer = __dependency2__["default"];
69
+ var ActiveModelAdapter = __dependency3__["default"];
70
+
71
+ Ember.onLoad('Ember.Application', function(Application) {
72
+ Application.initializer({
73
+ name: "activeModelAdapter",
74
+
75
+ initialize: function(container, application) {
76
+ var proxy = new ContainerProxy(container);
77
+ proxy.registerDeprecations([
78
+ {deprecated: 'serializer:_ams', valid: 'serializer:-active-model'},
79
+ {deprecated: 'adapter:_ams', valid: 'adapter:-active-model'}
80
+ ]);
81
+
82
+ application.register('serializer:-active-model', ActiveModelSerializer);
83
+ application.register('adapter:-active-model', ActiveModelAdapter);
84
+ }
85
+ });
86
+ });
87
+ });
88
+ define("activemodel-adapter/lib/main",
89
+ ["./system","./initializers","exports"],
90
+ function(__dependency1__, __dependency2__, __exports__) {
91
+ "use strict";
92
+ var ActiveModelAdapter = __dependency1__.ActiveModelAdapter;
93
+ var ActiveModelSerializer = __dependency1__.ActiveModelSerializer;
94
+ var EmbeddedRecordsMixin = __dependency1__.EmbeddedRecordsMixin;
95
+
96
+
97
+ __exports__.ActiveModelAdapter = ActiveModelAdapter;
98
+ __exports__.ActiveModelSerializer = ActiveModelSerializer;
99
+ __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
70
100
  });
101
+ define("activemodel-adapter/lib/system",
102
+ ["./system/embedded_records_mixin","./system/active_model_adapter","./system/active_model_serializer","exports"],
103
+ function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
104
+ "use strict";
105
+ var EmbeddedRecordsMixin = __dependency1__["default"];
106
+ var ActiveModelAdapter = __dependency2__["default"];
107
+ var ActiveModelSerializer = __dependency3__["default"];
108
+
109
+ __exports__.EmbeddedRecordsMixin = EmbeddedRecordsMixin;
110
+ __exports__.ActiveModelAdapter = ActiveModelAdapter;
111
+ __exports__.ActiveModelSerializer = ActiveModelSerializer;
112
+ });
113
+ define("activemodel-adapter/lib/system/active_model_adapter",
114
+ ["../../../ember-data/lib/adapters","../../../ember-data/lib/system/adapter","../../../ember-inflector/lib/main","./active_model_serializer","./embedded_records_mixin","exports"],
115
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
116
+ "use strict";
117
+ var RESTAdapter = __dependency1__.RESTAdapter;
118
+ var InvalidError = __dependency2__.InvalidError;
119
+ var pluralize = __dependency3__.pluralize;
120
+ var ActiveModelSerializer = __dependency4__["default"];
121
+ var EmbeddedRecordsMixin = __dependency5__["default"];
122
+
123
+ /**
124
+ @module ember-data
125
+ */
126
+
127
+ var forEach = Ember.EnumerableUtils.forEach;
128
+ var decamelize = Ember.String.decamelize,
129
+ underscore = Ember.String.underscore;
130
+
131
+ /**
132
+ The ActiveModelAdapter is a subclass of the RESTAdapter designed to integrate
133
+ with a JSON API that uses an underscored naming convention instead of camelcasing.
134
+ It has been designed to work out of the box with the
135
+ [active_model_serializers](http://github.com/rails-api/active_model_serializers)
136
+ Ruby gem.
137
+
138
+ This adapter extends the DS.RESTAdapter by making consistent use of the camelization,
139
+ decamelization and pluralization methods to normalize the serialized JSON into a
140
+ format that is compatible with a conventional Rails backend and Ember Data.
141
+
142
+ ## JSON Structure
143
+
144
+ The ActiveModelAdapter expects the JSON returned from your server to follow
145
+ the REST adapter conventions substituting underscored keys for camelcased ones.
146
+
147
+ ### Conventional Names
148
+
149
+ Attribute names in your JSON payload should be the underscored versions of
150
+ the attributes in your Ember.js models.
151
+
152
+ For example, if you have a `Person` model:
153
+
154
+ ```js
155
+ App.FamousPerson = DS.Model.extend({
156
+ firstName: DS.attr('string'),
157
+ lastName: DS.attr('string'),
158
+ occupation: DS.attr('string')
159
+ });
160
+ ```
71
161
 
72
- if ('undefined' !== typeof window) {
73
- window.DS = DS;
74
- }
162
+ The JSON returned should look like this:
75
163
 
76
- if (Ember.libraries) {
77
- Ember.libraries.registerCoreLibrary('Ember Data', DS.VERSION);
78
- }
79
- }
164
+ ```js
165
+ {
166
+ "famous_person": {
167
+ "first_name": "Barack",
168
+ "last_name": "Obama",
169
+ "occupation": "President"
170
+ }
171
+ }
172
+ ```
173
+
174
+ @class ActiveModelAdapter
175
+ @constructor
176
+ @namespace DS
177
+ @extends DS.Adapter
178
+ **/
179
+
180
+ var ActiveModelAdapter = RESTAdapter.extend({
181
+ defaultSerializer: '-active-model',
182
+ /**
183
+ The ActiveModelAdapter overrides the `pathForType` method to build
184
+ underscored URLs by decamelizing and pluralizing the object type name.
185
+
186
+ ```js
187
+ this.pathForType("famousPerson");
188
+ //=> "famous_people"
189
+ ```
190
+
191
+ @method pathForType
192
+ @param {String} type
193
+ @returns String
194
+ */
195
+ pathForType: function(type) {
196
+ var decamelized = decamelize(type);
197
+ var underscored = underscore(decamelized);
198
+ return pluralize(underscored);
199
+ },
80
200
 
81
- })();
201
+ /**
202
+ The ActiveModelAdapter overrides the `ajaxError` method
203
+ to return a DS.InvalidError for all 422 Unprocessable Entity
204
+ responses.
82
205
 
206
+ A 422 HTTP response from the server generally implies that the request
207
+ was well formed but the API was unable to process it because the
208
+ content was not semantically correct or meaningful per the API.
83
209
 
210
+ For more information on 422 HTTP Error code see 11.2 WebDAV RFC 4918
211
+ https://tools.ietf.org/html/rfc4918#section-11.2
84
212
 
85
- (function() {
86
- /**
87
- This is used internally to enable deprecation of container paths and provide
88
- a decent message to the user indicating how to fix the issue.
89
-
90
- @class ContainerProxy
91
- @namespace DS
92
- @private
93
- */
94
- var ContainerProxy = function (container){
95
- this.container = container;
96
- };
97
-
98
- ContainerProxy.prototype.aliasedFactory = function(path, preLookup) {
99
- var _this = this;
100
-
101
- return {create: function(){
102
- if (preLookup) { preLookup(); }
103
-
104
- return _this.container.lookup(path);
105
- }};
106
- };
107
-
108
- ContainerProxy.prototype.registerAlias = function(source, dest, preLookup) {
109
- var factory = this.aliasedFactory(dest, preLookup);
110
-
111
- return this.container.register(source, factory);
112
- };
113
-
114
- ContainerProxy.prototype.registerDeprecation = function(deprecated, valid) {
115
- var preLookupCallback = function(){
116
- Ember.deprecate("You tried to look up '" + deprecated + "', " +
117
- "but this has been deprecated in favor of '" + valid + "'.", false);
118
- };
213
+ @method ajaxError
214
+ @param jqXHR
215
+ @returns error
216
+ */
217
+ ajaxError: function(jqXHR) {
218
+ var error = this._super(jqXHR);
119
219
 
120
- return this.registerAlias(deprecated, valid, preLookupCallback);
121
- };
220
+ if (jqXHR && jqXHR.status === 422) {
221
+ var response = Ember.$.parseJSON(jqXHR.responseText),
222
+ errors = {};
122
223
 
123
- ContainerProxy.prototype.registerDeprecations = function(proxyPairs) {
124
- for (var i = proxyPairs.length; i > 0; i--) {
125
- var proxyPair = proxyPairs[i - 1],
126
- deprecated = proxyPair['deprecated'],
127
- valid = proxyPair['valid'];
224
+ if (response.errors !== undefined) {
225
+ var jsonErrors = response.errors;
128
226
 
129
- this.registerDeprecation(deprecated, valid);
130
- }
131
- };
227
+ forEach(Ember.keys(jsonErrors), function(key) {
228
+ errors[Ember.String.camelize(key)] = jsonErrors[key];
229
+ });
230
+ }
132
231
 
133
- DS.ContainerProxy = ContainerProxy;
232
+ return new InvalidError(errors);
233
+ } else {
234
+ return error;
235
+ }
236
+ }
237
+ });
134
238
 
135
- })();
239
+ __exports__["default"] = ActiveModelAdapter;
240
+ });
241
+ define("activemodel-adapter/lib/system/active_model_serializer",
242
+ ["../../../ember-inflector/lib/main","../../../ember-data/lib/serializers/rest_serializer","exports"],
243
+ function(__dependency1__, __dependency2__, __exports__) {
244
+ "use strict";
245
+ var singularize = __dependency1__.singularize;
246
+ var RESTSerializer = __dependency2__["default"];
247
+ /**
248
+ @module ember-data
249
+ */
250
+
251
+ var get = Ember.get,
252
+ forEach = Ember.EnumerableUtils.forEach,
253
+ camelize = Ember.String.camelize,
254
+ capitalize = Ember.String.capitalize,
255
+ decamelize = Ember.String.decamelize,
256
+ underscore = Ember.String.underscore;
257
+
258
+ var ActiveModelSerializer = RESTSerializer.extend({
259
+ // SERIALIZE
260
+
261
+ /**
262
+ Converts camelcased attributes to underscored when serializing.
263
+
264
+ @method keyForAttribute
265
+ @param {String} attribute
266
+ @returns String
267
+ */
268
+ keyForAttribute: function(attr) {
269
+ return decamelize(attr);
270
+ },
136
271
 
272
+ /**
273
+ Underscores relationship names and appends "_id" or "_ids" when serializing
274
+ relationship keys.
275
+
276
+ @method keyForRelationship
277
+ @param {String} key
278
+ @param {String} kind
279
+ @returns String
280
+ */
281
+ keyForRelationship: function(key, kind) {
282
+ key = decamelize(key);
283
+ if (kind === "belongsTo") {
284
+ return key + "_id";
285
+ } else if (kind === "hasMany") {
286
+ return singularize(key) + "_ids";
287
+ } else {
288
+ return key;
289
+ }
290
+ },
137
291
 
292
+ /**
293
+ Does not serialize hasMany relationships by default.
294
+ */
295
+ serializeHasMany: Ember.K,
138
296
 
139
- (function() {
140
- var get = Ember.get, set = Ember.set, isNone = Ember.isNone;
297
+ /**
298
+ Underscores the JSON root keys when serializing.
141
299
 
142
- // Simple dispatcher to support overriding the aliased
143
- // method in subclasses.
144
- function aliasMethod(methodName) {
145
- return function() {
146
- return this[methodName].apply(this, arguments);
147
- };
148
- }
149
-
150
- /**
151
- In Ember Data a Serializer is used to serialize and deserialize
152
- records when they are transferred in and out of an external source.
153
- This process involves normalizing property names, transforming
154
- attribute values and serializing relationships.
155
-
156
- For maximum performance Ember Data recommends you use the
157
- [RESTSerializer](DS.RESTSerializer.html) or one of its subclasses.
158
-
159
- `JSONSerializer` is useful for simpler or legacy backends that may
160
- not support the http://jsonapi.org/ spec.
161
-
162
- @class JSONSerializer
163
- @namespace DS
164
- */
165
- DS.JSONSerializer = Ember.Object.extend({
166
- /**
167
- The primaryKey is used when serializing and deserializing
168
- data. Ember Data always uses the `id` property to store the id of
169
- the record. The external source may not always follow this
170
- convention. In these cases it is useful to override the
171
- primaryKey property to match the primaryKey of your external
172
- store.
173
-
174
- Example
175
-
176
- ```javascript
177
- App.ApplicationSerializer = DS.JSONSerializer.extend({
178
- primaryKey: '_id'
179
- });
180
- ```
181
-
182
- @property primaryKey
183
- @type {String}
184
- @default 'id'
185
- */
186
- primaryKey: 'id',
187
-
188
- /**
189
- Given a subclass of `DS.Model` and a JSON object this method will
190
- iterate through each attribute of the `DS.Model` and invoke the
191
- `DS.Transform#deserialize` method on the matching property of the
192
- JSON object. This method is typically called after the
193
- serializer's `normalize` method.
194
-
195
- @method applyTransforms
196
- @private
197
- @param {subclass of DS.Model} type
198
- @param {Object} data The data to transform
199
- @return {Object} data The transformed data object
200
- */
201
- applyTransforms: function(type, data) {
202
- type.eachTransformedAttribute(function(key, type) {
203
- var transform = this.transformFor(type);
204
- data[key] = transform.deserialize(data[key]);
205
- }, this);
206
-
207
- return data;
208
- },
209
-
210
- /**
211
- Normalizes a part of the JSON payload returned by
212
- the server. You should override this method, munge the hash
213
- and call super if you have generic normalization to do.
214
-
215
- It takes the type of the record that is being normalized
216
- (as a DS.Model class), the property where the hash was
217
- originally found, and the hash to normalize.
218
-
219
- You can use this method, for example, to normalize underscored keys to camelized
220
- or other general-purpose normalizations.
221
-
222
- Example
223
-
224
- ```javascript
225
- App.ApplicationSerializer = DS.JSONSerializer.extend({
226
- normalize: function(type, hash) {
227
- var fields = Ember.get(type, 'fields');
228
- fields.forEach(function(field) {
229
- var payloadField = Ember.String.underscore(field);
230
- if (field === payloadField) { return; }
300
+ @method serializeIntoHash
301
+ @param {Object} hash
302
+ @param {subclass of DS.Model} type
303
+ @param {DS.Model} record
304
+ @param {Object} options
305
+ */
306
+ serializeIntoHash: function(data, type, record, options) {
307
+ var root = underscore(decamelize(type.typeKey));
308
+ data[root] = this.serialize(record, options);
309
+ },
231
310
 
232
- hash[field] = hash[payloadField];
233
- delete hash[payloadField];
234
- });
235
- return this._super.apply(this, arguments);
236
- }
237
- });
238
- ```
311
+ /**
312
+ Serializes a polymorphic type as a fully capitalized model name.
239
313
 
240
- @method normalize
241
- @param {subclass of DS.Model} type
242
- @param {Object} hash
243
- @return {Object}
244
- */
245
- normalize: function(type, hash) {
246
- if (!hash) { return hash; }
314
+ @method serializePolymorphicType
315
+ @param {DS.Model} record
316
+ @param {Object} json
317
+ @param relationship
318
+ */
319
+ serializePolymorphicType: function(record, json, relationship) {
320
+ var key = relationship.key,
321
+ belongsTo = get(record, key);
322
+ key = this.keyForAttribute(key);
323
+ json[key + "_type"] = capitalize(camelize(belongsTo.constructor.typeKey));
324
+ },
247
325
 
248
- this.applyTransforms(type, hash);
249
- return hash;
250
- },
326
+ // EXTRACT
251
327
 
252
- // SERIALIZE
253
- /**
254
- Called when a record is saved in order to convert the
255
- record into JSON.
328
+ /**
329
+ Extracts the model typeKey from underscored root objects.
256
330
 
257
- By default, it creates a JSON object with a key for
258
- each attribute and belongsTo relationship.
331
+ @method typeForRoot
332
+ @param {String} root
333
+ @returns String the model's typeKey
334
+ */
335
+ typeForRoot: function(root) {
336
+ var camelized = camelize(root);
337
+ return singularize(camelized);
338
+ },
259
339
 
260
- For example, consider this model:
340
+ /**
341
+ Add extra step to `DS.RESTSerializer.normalize` so links are
342
+ normalized.
261
343
 
262
- ```javascript
263
- App.Comment = DS.Model.extend({
264
- title: DS.attr(),
265
- body: DS.attr(),
344
+ If your payload looks like this
266
345
 
267
- author: DS.belongsTo('user')
268
- });
269
- ```
346
+ ```js
347
+ {
348
+ "post": {
349
+ "id": 1,
350
+ "title": "Rails is omakase",
351
+ "links": { "flagged_comments": "api/comments/flagged" }
352
+ }
353
+ }
354
+ ```
355
+ The normalized version would look like this
356
+
357
+ ```js
358
+ {
359
+ "post": {
360
+ "id": 1,
361
+ "title": "Rails is omakase",
362
+ "links": { "flaggedComments": "api/comments/flagged" }
363
+ }
364
+ }
365
+ ```
270
366
 
271
- The default serialization would create a JSON object like:
367
+ @method normalize
368
+ @param {subclass of DS.Model} type
369
+ @param {Object} hash
370
+ @param {String} prop
371
+ @returns Object
372
+ */
272
373
 
273
- ```javascript
274
- {
275
- "title": "Rails is unagi",
276
- "body": "Rails? Omakase? O_O",
277
- "author": 12
278
- }
279
- ```
374
+ normalize: function(type, hash, prop) {
375
+ this.normalizeLinks(hash);
376
+
377
+ return this._super(type, hash, prop);
378
+ },
280
379
 
281
- By default, attributes are passed through as-is, unless
282
- you specified an attribute type (`DS.attr('date')`). If
283
- you specify a transform, the JavaScript value will be
284
- serialized when inserted into the JSON hash.
380
+ /**
381
+ Convert `snake_cased` links to `camelCase`
285
382
 
286
- By default, belongs-to relationships are converted into
287
- IDs when inserted into the JSON hash.
383
+ @method normalizeLinks
384
+ @param {Object} hash
385
+ */
288
386
 
289
- ## IDs
387
+ normalizeLinks: function(data){
388
+ if (data.links) {
389
+ var links = data.links;
290
390
 
291
- `serialize` takes an options hash with a single option:
292
- `includeId`. If this option is `true`, `serialize` will,
293
- by default include the ID in the JSON object it builds.
391
+ for (var link in links) {
392
+ var camelizedLink = camelize(link);
294
393
 
295
- The adapter passes in `includeId: true` when serializing
296
- a record for `createRecord`, but not for `updateRecord`.
394
+ if (camelizedLink !== link) {
395
+ links[camelizedLink] = links[link];
396
+ delete links[link];
397
+ }
398
+ }
399
+ }
400
+ },
297
401
 
298
- ## Customization
402
+ /**
403
+ Normalize the polymorphic type from the JSON.
299
404
 
300
- Your server may expect a different JSON format than the
301
- built-in serialization format.
405
+ Normalize:
406
+ ```js
407
+ {
408
+ id: "1"
409
+ minion: { type: "evil_minion", id: "12"}
410
+ }
411
+ ```
302
412
 
303
- In that case, you can implement `serialize` yourself and
304
- return a JSON hash of your choosing.
413
+ To:
414
+ ```js
415
+ {
416
+ id: "1"
417
+ minion: { type: "evilMinion", id: "12"}
418
+ }
419
+ ```
420
+
421
+ @method normalizeRelationships
422
+ @private
423
+ */
424
+ normalizeRelationships: function(type, hash) {
425
+ var payloadKey, payload;
426
+
427
+ if (this.keyForRelationship) {
428
+ type.eachRelationship(function(key, relationship) {
429
+ if (relationship.options.polymorphic) {
430
+ payloadKey = this.keyForAttribute(key);
431
+ payload = hash[payloadKey];
432
+ if (payload && payload.type) {
433
+ payload.type = this.typeForRoot(payload.type);
434
+ } else if (payload && relationship.kind === "hasMany") {
435
+ var self = this;
436
+ forEach(payload, function(single) {
437
+ single.type = self.typeForRoot(single.type);
438
+ });
439
+ }
440
+ } else {
441
+ payloadKey = this.keyForRelationship(key, relationship.kind);
442
+ payload = hash[payloadKey];
443
+ }
305
444
 
306
- ```javascript
307
- App.PostSerializer = DS.JSONSerializer.extend({
308
- serialize: function(post, options) {
309
- var json = {
310
- POST_TTL: post.get('title'),
311
- POST_BDY: post.get('body'),
312
- POST_CMS: post.get('comments').mapProperty('id')
313
- }
445
+ hash[key] = payload;
314
446
 
315
- if (options.includeId) {
316
- json.POST_ID_ = post.get('id');
447
+ if (key !== payloadKey) {
448
+ delete hash[payloadKey];
449
+ }
450
+ }, this);
317
451
  }
318
-
319
- return json;
320
452
  }
321
453
  });
322
- ```
323
454
 
324
- ## Customizing an App-Wide Serializer
455
+ __exports__["default"] = ActiveModelSerializer;
456
+ });
457
+ define("activemodel-adapter/lib/system/embedded_records_mixin",
458
+ ["../../../ember-inflector/lib/main","exports"],
459
+ function(__dependency1__, __exports__) {
460
+ "use strict";
461
+ var get = Ember.get;
462
+ var forEach = Ember.EnumerableUtils.forEach;
325
463
 
326
- If you want to define a serializer for your entire
327
- application, you'll probably want to use `eachAttribute`
328
- and `eachRelationship` on the record.
464
+ var pluralize = __dependency1__.pluralize;
329
465
 
330
- ```javascript
331
- App.ApplicationSerializer = DS.JSONSerializer.extend({
332
- serialize: function(record, options) {
333
- var json = {};
466
+ /**
467
+ The EmbeddedRecordsMixin allows you to add embedded record support to your
468
+ serializers.
469
+ To set up embedded records, you include the mixin into the serializer and then
470
+ define your embedded relations.
334
471
 
335
- record.eachAttribute(function(name) {
336
- json[serverAttributeName(name)] = record.get(name);
337
- })
472
+ ```js
473
+ App.PostSerializer = DS.ActiveModelSerializer.extend(DS.EmbeddedRecordsMixin, {
474
+ attrs: {
475
+ comments: {embedded: 'always'}
476
+ }
477
+ })
478
+ ```
338
479
 
339
- record.eachRelationship(function(name, relationship) {
340
- if (relationship.kind === 'hasMany') {
341
- json[serverHasManyName(name)] = record.get(name).mapBy('id');
342
- }
343
- });
480
+ Currently only `{embedded: 'always'}` records are supported.
344
481
 
345
- if (options.includeId) {
346
- json.ID_ = record.get('id');
347
- }
482
+ @class EmbeddedRecordsMixin
483
+ @namespace DS
484
+ */
485
+ var EmbeddedRecordsMixin = Ember.Mixin.create({
348
486
 
349
- return json;
350
- }
351
- });
487
+ /**
488
+ Serialize has-may relationship when it is configured as embedded objects.
352
489
 
353
- function serverAttributeName(attribute) {
354
- return attribute.underscore().toUpperCase();
355
- }
490
+ @method serializeHasMany
491
+ */
492
+ serializeHasMany: function(record, json, relationship) {
493
+ var key = relationship.key,
494
+ attrs = get(this, 'attrs'),
495
+ embed = attrs && attrs[key] && attrs[key].embedded === 'always';
356
496
 
357
- function serverHasManyName(name) {
358
- return serverAttributeName(name.singularize()) + "_IDS";
359
- }
360
- ```
497
+ if (embed) {
498
+ json[this.keyForAttribute(key)] = get(record, key).map(function(relation) {
499
+ var data = relation.serialize(),
500
+ primaryKey = get(this, 'primaryKey');
361
501
 
362
- This serializer will generate JSON that looks like this:
502
+ data[primaryKey] = get(relation, primaryKey);
363
503
 
364
- ```javascript
365
- {
366
- "TITLE": "Rails is omakase",
367
- "BODY": "Yep. Omakase.",
368
- "COMMENT_IDS": [ 1, 2, 3 ]
369
- }
370
- ```
504
+ return data;
505
+ }, this);
506
+ }
507
+ },
371
508
 
372
- ## Tweaking the Default JSON
509
+ /**
510
+ Extract embedded objects out of the payload for a single object
511
+ and add them as sideloaded objects instead.
373
512
 
374
- If you just want to do some small tweaks on the default JSON,
375
- you can call super first and make the tweaks on the returned
376
- JSON.
513
+ @method extractSingle
514
+ */
515
+ extractSingle: function(store, primaryType, payload, recordId, requestType) {
516
+ var root = this.keyForAttribute(primaryType.typeKey),
517
+ partial = payload[root];
377
518
 
378
- ```javascript
379
- App.PostSerializer = DS.JSONSerializer.extend({
380
- serialize: function(record, options) {
381
- var json = this._super.apply(this, arguments);
519
+ updatePayloadWithEmbedded(store, this, primaryType, partial, payload);
382
520
 
383
- json.subject = json.title;
384
- delete json.title;
521
+ return this._super(store, primaryType, payload, recordId, requestType);
522
+ },
385
523
 
386
- return json;
387
- }
388
- });
389
- ```
524
+ /**
525
+ Extract embedded objects out of a standard payload
526
+ and add them as sideloaded objects instead.
390
527
 
391
- @method serialize
392
- @param {subclass of DS.Model} record
393
- @param {Object} options
394
- @return {Object} json
395
- */
396
- serialize: function(record, options) {
397
- var json = {};
528
+ @method extractArray
529
+ */
530
+ extractArray: function(store, type, payload) {
531
+ var root = this.keyForAttribute(type.typeKey),
532
+ partials = payload[pluralize(root)];
398
533
 
399
- if (options && options.includeId) {
400
- var id = get(record, 'id');
534
+ forEach(partials, function(partial) {
535
+ updatePayloadWithEmbedded(store, this, type, partial, payload);
536
+ }, this);
401
537
 
402
- if (id) {
403
- json[get(this, 'primaryKey')] = id;
538
+ return this._super(store, type, payload);
404
539
  }
405
- }
540
+ });
406
541
 
407
- record.eachAttribute(function(key, attribute) {
408
- this.serializeAttribute(record, json, key, attribute);
409
- }, this);
542
+ function updatePayloadWithEmbedded(store, serializer, type, partial, payload) {
543
+ var attrs = get(serializer, 'attrs');
410
544
 
411
- record.eachRelationship(function(key, relationship) {
412
- if (relationship.kind === 'belongsTo') {
413
- this.serializeBelongsTo(record, json, relationship);
414
- } else if (relationship.kind === 'hasMany') {
415
- this.serializeHasMany(record, json, relationship);
545
+ if (!attrs) {
546
+ return;
416
547
  }
417
- }, this);
418
-
419
- return json;
420
- },
421
-
422
- /**
423
- `serializeAttribute` can be used to customize how `DS.attr`
424
- properties are serialized
425
-
426
- For example if you wanted to ensure all you attributes were always
427
- serialized as properties on an `attributes` object you could
428
- write:
429
-
430
- ```javascript
431
- App.ApplicationSerializer = DS.JSONSerializer.extend({
432
- serializeAttribute: function(record, json, key, attributes) {
433
- json.attributes = json.attributes || {};
434
- this._super(record, json.attributes, key, attributes);
435
- }
436
- });
437
- ```
438
-
439
- @method serializeAttribute
440
- @param {DS.Model} record
441
- @param {Object} json
442
- @param {String} key
443
- @param {Object} attribute
444
- */
445
- serializeAttribute: function(record, json, key, attribute) {
446
- var attrs = get(this, 'attrs');
447
- var value = get(record, key), type = attribute.type;
448
-
449
- if (type) {
450
- var transform = this.transformFor(type);
451
- value = transform.serialize(value);
452
- }
453
548
 
454
- // if provided, use the mapping provided by `attrs` in
455
- // the serializer
456
- key = attrs && attrs[key] || (this.keyForAttribute ? this.keyForAttribute(key) : key);
549
+ type.eachRelationship(function(key, relationship) {
550
+ var expandedKey, embeddedTypeKey, attribute, ids,
551
+ config = attrs[key],
552
+ serializer = store.serializerFor(relationship.type.typeKey),
553
+ primaryKey = get(serializer, "primaryKey");
457
554
 
458
- json[key] = value;
459
- },
555
+ if (relationship.kind !== "hasMany") {
556
+ return;
557
+ }
460
558
 
461
- /**
462
- `serializeBelongsTo` can be used to customize how `DS.belongsTo`
463
- properties are serialized.
559
+ if (config && (config.embedded === 'always' || config.embedded === 'load')) {
560
+ // underscore forces the embedded records to be side loaded.
561
+ // it is needed when main type === relationship.type
562
+ embeddedTypeKey = '_' + Ember.String.pluralize(relationship.type.typeKey);
563
+ expandedKey = this.keyForRelationship(key, relationship.kind);
564
+ attribute = this.keyForAttribute(key);
565
+ ids = [];
464
566
 
465
- Example
567
+ if (!partial[attribute]) {
568
+ return;
569
+ }
466
570
 
467
- ```javascript
468
- App.PostSerializer = DS.JSONSerializer.extend({
469
- serializeBelongsTo: function(record, json, relationship) {
470
- var key = relationship.key;
571
+ payload[embeddedTypeKey] = payload[embeddedTypeKey] || [];
471
572
 
472
- var belongsTo = get(record, key);
573
+ forEach(partial[attribute], function(data) {
574
+ var embeddedType = store.modelFor(relationship.type.typeKey);
575
+ updatePayloadWithEmbedded(store, serializer, embeddedType, data, payload);
576
+ ids.push(data[primaryKey]);
577
+ payload[embeddedTypeKey].push(data);
578
+ });
473
579
 
474
- key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;
580
+ partial[expandedKey] = ids;
581
+ delete partial[attribute];
582
+ }
583
+ }, serializer);
584
+ }
475
585
 
476
- json[key] = Ember.isNone(belongsTo) ? belongsTo : belongsTo.toJSON();
477
- }
478
- });
479
- ```
586
+ __exports__["default"] = EmbeddedRecordsMixin;
587
+ });
588
+ define("ember-data/lib/adapters",
589
+ ["./adapters/fixture_adapter","./adapters/rest_adapter","exports"],
590
+ function(__dependency1__, __dependency2__, __exports__) {
591
+ "use strict";
592
+ /**
593
+ @module ember-data
594
+ */
595
+
596
+ var FixtureAdapter = __dependency1__["default"];
597
+ var RESTAdapter = __dependency2__["default"];
598
+
599
+ __exports__.RESTAdapter = RESTAdapter;
600
+ __exports__.FixtureAdapter = FixtureAdapter;
601
+ });
602
+ define("ember-data/lib/adapters/fixture_adapter",
603
+ ["../system/adapter","exports"],
604
+ function(__dependency1__, __exports__) {
605
+ "use strict";
606
+ /**
607
+ @module ember-data
608
+ */
609
+
610
+ var get = Ember.get, fmt = Ember.String.fmt,
611
+ indexOf = Ember.EnumerableUtils.indexOf;
612
+
613
+ var counter = 0;
614
+
615
+ var Adapter = __dependency1__["default"];
616
+
617
+ /**
618
+ `DS.FixtureAdapter` is an adapter that loads records from memory.
619
+ Its primarily used for development and testing. You can also use
620
+ `DS.FixtureAdapter` while working on the API but are not ready to
621
+ integrate yet. It is a fully functioning adapter. All CRUD methods
622
+ are implemented. You can also implement query logic that a remote
623
+ system would do. Its possible to do develop your entire application
624
+ with `DS.FixtureAdapter`.
625
+
626
+ For information on how to use the `FixtureAdapter` in your
627
+ application please see the [FixtureAdapter
628
+ guide](/guides/models/the-fixture-adapter/).
629
+
630
+ @class FixtureAdapter
631
+ @namespace DS
632
+ @extends DS.Adapter
633
+ */
634
+ var FixtureAdapter = Adapter.extend({
635
+ // by default, fixtures are already in normalized form
636
+ serializer: null,
637
+
638
+ /**
639
+ If `simulateRemoteResponse` is `true` the `FixtureAdapter` will
640
+ wait a number of milliseconds before resolving promises with the
641
+ fixture values. The wait time can be configured via the `latency`
642
+ property.
643
+
644
+ @property simulateRemoteResponse
645
+ @type {Boolean}
646
+ @default true
647
+ */
648
+ simulateRemoteResponse: true,
649
+
650
+ /**
651
+ By default the `FixtureAdapter` will simulate a wait of the
652
+ `latency` milliseconds before resolving promises with the fixture
653
+ values. This behavior can be turned off via the
654
+ `simulateRemoteResponse` property.
655
+
656
+ @property latency
657
+ @type {Number}
658
+ @default 50
659
+ */
660
+ latency: 50,
661
+
662
+ /**
663
+ Implement this method in order to provide data associated with a type
664
+
665
+ @method fixturesForType
666
+ @param {Subclass of DS.Model} type
667
+ @return {Array}
668
+ */
669
+ fixturesForType: function(type) {
670
+ if (type.FIXTURES) {
671
+ var fixtures = Ember.A(type.FIXTURES);
672
+ return fixtures.map(function(fixture){
673
+ var fixtureIdType = typeof fixture.id;
674
+ if(fixtureIdType !== "number" && fixtureIdType !== "string"){
675
+ throw new Error(fmt('the id property must be defined as a number or string for fixture %@', [fixture]));
676
+ }
677
+ fixture.id = fixture.id + '';
678
+ return fixture;
679
+ });
680
+ }
681
+ return null;
682
+ },
480
683
 
481
- @method serializeBelongsTo
482
- @param {DS.Model} record
483
- @param {Object} json
484
- @param {Object} relationship
485
- */
486
- serializeBelongsTo: function(record, json, relationship) {
487
- var key = relationship.key;
684
+ /**
685
+ Implement this method in order to query fixtures data
686
+
687
+ @method queryFixtures
688
+ @param {Array} fixture
689
+ @param {Object} query
690
+ @param {Subclass of DS.Model} type
691
+ @return {Promise|Array}
692
+ */
693
+ queryFixtures: function(fixtures, query, type) {
694
+ Ember.assert('Not implemented: You must override the DS.FixtureAdapter::queryFixtures method to support querying the fixture store.');
695
+ },
488
696
 
489
- var belongsTo = get(record, key);
697
+ /**
698
+ @method updateFixtures
699
+ @param {Subclass of DS.Model} type
700
+ @param {Array} fixture
701
+ */
702
+ updateFixtures: function(type, fixture) {
703
+ if(!type.FIXTURES) {
704
+ type.FIXTURES = [];
705
+ }
490
706
 
491
- key = this.keyForRelationship ? this.keyForRelationship(key, "belongsTo") : key;
707
+ var fixtures = type.FIXTURES;
492
708
 
493
- if (isNone(belongsTo)) {
494
- json[key] = belongsTo;
495
- } else {
496
- json[key] = get(belongsTo, 'id');
497
- }
709
+ this.deleteLoadedFixture(type, fixture);
498
710
 
499
- if (relationship.options.polymorphic) {
500
- this.serializePolymorphicType(record, json, relationship);
501
- }
502
- },
503
-
504
- /**
505
- `serializeHasMany` can be used to customize how `DS.hasMany`
506
- properties are serialized.
507
-
508
- Example
509
-
510
- ```javascript
511
- App.PostSerializer = DS.JSONSerializer.extend({
512
- serializeHasMany: function(record, json, relationship) {
513
- var key = relationship.key;
514
- if (key === 'comments') {
515
- return;
516
- } else {
517
- this._super.apply(this, arguments);
518
- }
519
- }
520
- });
521
- ```
522
-
523
- @method serializeHasMany
524
- @param {DS.Model} record
525
- @param {Object} json
526
- @param {Object} relationship
527
- */
528
- serializeHasMany: function(record, json, relationship) {
529
- var key = relationship.key;
530
-
531
- var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
532
-
533
- if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany') {
534
- json[key] = get(record, key).mapBy('id');
535
- // TODO support for polymorphic manyToNone and manyToMany relationships
536
- }
537
- },
711
+ fixtures.push(fixture);
712
+ },
538
713
 
539
- /**
540
- You can use this method to customize how polymorphic objects are
541
- serialized. Objects are considered to be polymorphic if
542
- `{polymorphic: true}` is pass as the second argument to the
543
- `DS.belongsTo` function.
714
+ /**
715
+ Implement this method in order to provide json for CRUD methods
544
716
 
545
- Example
717
+ @method mockJSON
718
+ @param {Subclass of DS.Model} type
719
+ @param {DS.Model} record
720
+ */
721
+ mockJSON: function(store, type, record) {
722
+ return store.serializerFor(type).serialize(record, { includeId: true });
723
+ },
546
724
 
547
- ```javascript
548
- App.CommentSerializer = DS.JSONSerializer.extend({
549
- serializePolymorphicType: function(record, json, relationship) {
550
- var key = relationship.key,
551
- belongsTo = get(record, key);
552
- key = this.keyForAttribute ? this.keyForAttribute(key) : key;
553
- json[key + "_type"] = belongsTo.constructor.typeKey;
554
- }
555
- });
556
- ```
725
+ /**
726
+ @method generateIdForRecord
727
+ @param {DS.Store} store
728
+ @param {DS.Model} record
729
+ @return {String} id
730
+ */
731
+ generateIdForRecord: function(store) {
732
+ return "fixture-" + counter++;
733
+ },
557
734
 
558
- @method serializePolymorphicType
559
- @param {DS.Model} record
560
- @param {Object} json
561
- @param {Object} relationship
562
- */
563
- serializePolymorphicType: Ember.K,
735
+ /**
736
+ @method find
737
+ @param {DS.Store} store
738
+ @param {subclass of DS.Model} type
739
+ @param {String} id
740
+ @return {Promise} promise
741
+ */
742
+ find: function(store, type, id) {
743
+ var fixtures = this.fixturesForType(type),
744
+ fixture;
564
745
 
565
- // EXTRACT
746
+ Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);
566
747
 
567
- /**
568
- The `extract` method is used to deserialize payload data from the
569
- server. By default the `JSONSerializer` does not push the records
570
- into the store. However records that subclass `JSONSerializer`
571
- such as the `RESTSerializer` may push records into the store as
572
- part of the extract call.
748
+ if (fixtures) {
749
+ fixture = Ember.A(fixtures).findProperty('id', id);
750
+ }
573
751
 
574
- This method delegates to a more specific extract method based on
575
- the `requestType`.
752
+ if (fixture) {
753
+ return this.simulateRemoteCall(function() {
754
+ return fixture;
755
+ }, this);
756
+ }
757
+ },
576
758
 
577
- Example
759
+ /**
760
+ @method findMany
761
+ @param {DS.Store} store
762
+ @param {subclass of DS.Model} type
763
+ @param {Array} ids
764
+ @return {Promise} promise
765
+ */
766
+ findMany: function(store, type, ids) {
767
+ var fixtures = this.fixturesForType(type);
578
768
 
579
- ```javascript
580
- var get = Ember.get;
581
- socket.on('message', function(message) {
582
- var modelName = message.model;
583
- var data = message.data;
584
- var type = store.modelFor(modelName);
585
- var serializer = store.serializerFor(type.typeKey);
586
- var record = serializer.extract(store, type, data, get(data, 'id'), 'single');
587
- store.push(modelName, record);
588
- });
589
- ```
590
-
591
- @method extract
592
- @param {DS.Store} store
593
- @param {subclass of DS.Model} type
594
- @param {Object} payload
595
- @param {String or Number} id
596
- @param {String} requestType
597
- @return {Object} json The deserialized payload
598
- */
599
- extract: function(store, type, payload, id, requestType) {
600
- this.extractMeta(store, type, payload);
601
-
602
- var specificExtract = "extract" + requestType.charAt(0).toUpperCase() + requestType.substr(1);
603
- return this[specificExtract](store, type, payload, id, requestType);
604
- },
605
-
606
- /**
607
- `extractFindAll` is a hook into the extract method used when a
608
- call is made to `DS.Store#findAll`. By default this method is an
609
- alias for [extractArray](#method_extractArray).
610
-
611
- @method extractFindAll
612
- @param {DS.Store} store
613
- @param {subclass of DS.Model} type
614
- @param {Object} payload
615
- @return {Array} array An array of deserialized objects
616
- */
617
- extractFindAll: aliasMethod('extractArray'),
618
- /**
619
- `extractFindQuery` is a hook into the extract method used when a
620
- call is made to `DS.Store#findQuery`. By default this method is an
621
- alias for [extractArray](#method_extractArray).
622
-
623
- @method extractFindQuery
624
- @param {DS.Store} store
625
- @param {subclass of DS.Model} type
626
- @param {Object} payload
627
- @return {Array} array An array of deserialized objects
628
- */
629
- extractFindQuery: aliasMethod('extractArray'),
630
- /**
631
- `extractFindMany` is a hook into the extract method used when a
632
- call is made to `DS.Store#findMany`. By default this method is
633
- alias for [extractArray](#method_extractArray).
634
-
635
- @method extractFindMany
636
- @param {DS.Store} store
637
- @param {subclass of DS.Model} type
638
- @param {Object} payload
639
- @return {Array} array An array of deserialized objects
640
- */
641
- extractFindMany: aliasMethod('extractArray'),
642
- /**
643
- `extractFindHasMany` is a hook into the extract method used when a
644
- call is made to `DS.Store#findHasMany`. By default this method is
645
- alias for [extractArray](#method_extractArray).
646
-
647
- @method extractFindHasMany
648
- @param {DS.Store} store
649
- @param {subclass of DS.Model} type
650
- @param {Object} payload
651
- @return {Array} array An array of deserialized objects
652
- */
653
- extractFindHasMany: aliasMethod('extractArray'),
654
-
655
- /**
656
- `extractCreateRecord` is a hook into the extract method used when a
657
- call is made to `DS.Store#createRecord`. By default this method is
658
- alias for [extractSave](#method_extractSave).
659
-
660
- @method extractCreateRecord
661
- @param {DS.Store} store
662
- @param {subclass of DS.Model} type
663
- @param {Object} payload
664
- @return {Object} json The deserialized payload
665
- */
666
- extractCreateRecord: aliasMethod('extractSave'),
667
- /**
668
- `extractUpdateRecord` is a hook into the extract method used when
669
- a call is made to `DS.Store#update`. By default this method is alias
670
- for [extractSave](#method_extractSave).
671
-
672
- @method extractUpdateRecord
673
- @param {DS.Store} store
674
- @param {subclass of DS.Model} type
675
- @param {Object} payload
676
- @return {Object} json The deserialized payload
677
- */
678
- extractUpdateRecord: aliasMethod('extractSave'),
679
- /**
680
- `extractDeleteRecord` is a hook into the extract method used when
681
- a call is made to `DS.Store#deleteRecord`. By default this method is
682
- alias for [extractSave](#method_extractSave).
683
-
684
- @method extractDeleteRecord
685
- @param {DS.Store} store
686
- @param {subclass of DS.Model} type
687
- @param {Object} payload
688
- @return {Object} json The deserialized payload
689
- */
690
- extractDeleteRecord: aliasMethod('extractSave'),
691
-
692
- /**
693
- `extractFind` is a hook into the extract method used when
694
- a call is made to `DS.Store#find`. By default this method is
695
- alias for [extractSingle](#method_extractSingle).
696
-
697
- @method extractFind
698
- @param {DS.Store} store
699
- @param {subclass of DS.Model} type
700
- @param {Object} payload
701
- @return {Object} json The deserialized payload
702
- */
703
- extractFind: aliasMethod('extractSingle'),
704
- /**
705
- `extractFindBelongsTo` is a hook into the extract method used when
706
- a call is made to `DS.Store#findBelongsTo`. By default this method is
707
- alias for [extractSingle](#method_extractSingle).
708
-
709
- @method extractFindBelongsTo
710
- @param {DS.Store} store
711
- @param {subclass of DS.Model} type
712
- @param {Object} payload
713
- @return {Object} json The deserialized payload
714
- */
715
- extractFindBelongsTo: aliasMethod('extractSingle'),
716
- /**
717
- `extractSave` is a hook into the extract method used when a call
718
- is made to `DS.Model#save`. By default this method is alias
719
- for [extractSingle](#method_extractSingle).
720
-
721
- @method extractSave
722
- @param {DS.Store} store
723
- @param {subclass of DS.Model} type
724
- @param {Object} payload
725
- @return {Object} json The deserialized payload
726
- */
727
- extractSave: aliasMethod('extractSingle'),
728
-
729
- /**
730
- `extractSingle` is used to deserialize a single record returned
731
- from the adapter.
732
-
733
- Example
734
-
735
- ```javascript
736
- App.PostSerializer = DS.JSONSerializer.extend({
737
- extractSingle: function(store, type, payload) {
738
- payload.comments = payload._embedded.comment;
739
- delete payload._embedded;
769
+ Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);
740
770
 
741
- return this._super(store, type, payload);
742
- },
743
- });
744
- ```
745
-
746
- @method extractSingle
747
- @param {DS.Store} store
748
- @param {subclass of DS.Model} type
749
- @param {Object} payload
750
- @return {Object} json The deserialized payload
751
- */
752
- extractSingle: function(store, type, payload) {
753
- return this.normalize(type, payload);
754
- },
755
-
756
- /**
757
- `extractArray` is used to deserialize an array of records
758
- returned from the adapter.
759
-
760
- Example
761
-
762
- ```javascript
763
- App.PostSerializer = DS.JSONSerializer.extend({
764
- extractArray: function(store, type, payload) {
765
- return payload.map(function(json) {
766
- return this.extractSingle(json);
767
- }, this);
768
- }
769
- });
770
- ```
771
-
772
- @method extractArray
773
- @param {DS.Store} store
774
- @param {subclass of DS.Model} type
775
- @param {Object} payload
776
- @return {Array} array An array of deserialized objects
777
- */
778
- extractArray: function(store, type, payload) {
779
- return this.normalize(type, payload);
780
- },
781
-
782
- /**
783
- `extractMeta` is used to deserialize any meta information in the
784
- adapter payload. By default Ember Data expects meta information to
785
- be located on the `meta` property of the payload object.
786
-
787
- Example
788
-
789
- ```javascript
790
- App.PostSerializer = DS.JSONSerializer.extend({
791
- extractMeta: function(store, type, payload) {
792
- if (payload && payload._pagination) {
793
- store.metaForType(type, payload._pagination);
794
- delete payload._pagination;
771
+ if (fixtures) {
772
+ fixtures = fixtures.filter(function(item) {
773
+ return indexOf(ids, item.id) !== -1;
774
+ });
795
775
  }
796
- }
797
- });
798
- ```
799
-
800
- @method extractMeta
801
- @param {DS.Store} store
802
- @param {subclass of DS.Model} type
803
- @param {Object} payload
804
- */
805
- extractMeta: function(store, type, payload) {
806
- if (payload && payload.meta) {
807
- store.metaForType(type, payload.meta);
808
- delete payload.meta;
809
- }
810
- },
811
776
 
812
- /**
813
- `keyForAttribute` can be used to define rules for how to convert an
814
- attribute name in your model to a key in your JSON.
777
+ if (fixtures) {
778
+ return this.simulateRemoteCall(function() {
779
+ return fixtures;
780
+ }, this);
781
+ }
782
+ },
783
+
784
+ /**
785
+ @private
786
+ @method findAll
787
+ @param {DS.Store} store
788
+ @param {subclass of DS.Model} type
789
+ @param {String} sinceToken
790
+ @return {Promise} promise
791
+ */
792
+ findAll: function(store, type) {
793
+ var fixtures = this.fixturesForType(type);
794
+
795
+ Ember.assert("Unable to find fixtures for model type "+type.toString(), fixtures);
796
+
797
+ return this.simulateRemoteCall(function() {
798
+ return fixtures;
799
+ }, this);
800
+ },
815
801
 
816
- Example
802
+ /**
803
+ @private
804
+ @method findQuery
805
+ @param {DS.Store} store
806
+ @param {subclass of DS.Model} type
807
+ @param {Object} query
808
+ @param {DS.AdapterPopulatedRecordArray} recordArray
809
+ @return {Promise} promise
810
+ */
811
+ findQuery: function(store, type, query, array) {
812
+ var fixtures = this.fixturesForType(type);
813
+
814
+ Ember.assert("Unable to find fixtures for model type " + type.toString(), fixtures);
815
+
816
+ fixtures = this.queryFixtures(fixtures, query, type);
817
+
818
+ if (fixtures) {
819
+ return this.simulateRemoteCall(function() {
820
+ return fixtures;
821
+ }, this);
822
+ }
823
+ },
817
824
 
818
- ```javascript
819
- App.ApplicationSerializer = DS.RESTSerializer.extend({
820
- keyForAttribute: function(attr) {
821
- return Ember.String.underscore(attr).toUpperCase();
822
- }
823
- });
824
- ```
825
+ /**
826
+ @method createRecord
827
+ @param {DS.Store} store
828
+ @param {subclass of DS.Model} type
829
+ @param {DS.Model} record
830
+ @return {Promise} promise
831
+ */
832
+ createRecord: function(store, type, record) {
833
+ var fixture = this.mockJSON(store, type, record);
825
834
 
826
- @method keyForAttribute
827
- @param {String} key
828
- @return {String} normalized key
829
- */
835
+ this.updateFixtures(type, fixture);
830
836
 
837
+ return this.simulateRemoteCall(function() {
838
+ return fixture;
839
+ }, this);
840
+ },
831
841
 
832
- /**
833
- `keyForRelationship` can be used to define a custom key when
834
- serializing relationship properties. By default `JSONSerializer`
835
- does not provide an implementation of this method.
842
+ /**
843
+ @method updateRecord
844
+ @param {DS.Store} store
845
+ @param {subclass of DS.Model} type
846
+ @param {DS.Model} record
847
+ @return {Promise} promise
848
+ */
849
+ updateRecord: function(store, type, record) {
850
+ var fixture = this.mockJSON(store, type, record);
836
851
 
837
- Example
852
+ this.updateFixtures(type, fixture);
838
853
 
839
- ```javascript
840
- App.PostSerializer = DS.JSONSerializer.extend({
841
- keyForRelationship: function(key, relationship) {
842
- return 'rel_' + Ember.String.underscore(key);
843
- }
844
- });
845
- ```
846
-
847
- @method keyForRelationship
848
- @param {String} key
849
- @param {String} relationship type
850
- @return {String} normalized key
851
- */
852
-
853
- // HELPERS
854
-
855
- /**
856
- @method transformFor
857
- @private
858
- @param {String} attributeType
859
- @param {Boolean} skipAssertion
860
- @return {DS.Transform} transform
861
- */
862
- transformFor: function(attributeType, skipAssertion) {
863
- var transform = this.container.lookup('transform:' + attributeType);
864
- Ember.assert("Unable to find transform for '" + attributeType + "'", skipAssertion || !!transform);
865
- return transform;
866
- }
867
- });
854
+ return this.simulateRemoteCall(function() {
855
+ return fixture;
856
+ }, this);
857
+ },
868
858
 
869
- })();
859
+ /**
860
+ @method deleteRecord
861
+ @param {DS.Store} store
862
+ @param {subclass of DS.Model} type
863
+ @param {DS.Model} record
864
+ @return {Promise} promise
865
+ */
866
+ deleteRecord: function(store, type, record) {
867
+ var fixture = this.mockJSON(store, type, record);
870
868
 
869
+ this.deleteLoadedFixture(type, fixture);
871
870
 
871
+ return this.simulateRemoteCall(function() {
872
+ // no payload in a deletion
873
+ return null;
874
+ });
875
+ },
872
876
 
873
- (function() {
874
- /**
875
- @module ember-data
876
- */
877
- var get = Ember.get, capitalize = Ember.String.capitalize, underscore = Ember.String.underscore, DS = window.DS ;
878
-
879
- /**
880
- Extend `Ember.DataAdapter` with ED specific code.
881
-
882
- @class DebugAdapter
883
- @namespace DS
884
- @extends Ember.DataAdapter
885
- @private
886
- */
887
- DS.DebugAdapter = Ember.DataAdapter.extend({
888
- getFilters: function() {
889
- return [
890
- { name: 'isNew', desc: 'New' },
891
- { name: 'isModified', desc: 'Modified' },
892
- { name: 'isClean', desc: 'Clean' }
893
- ];
894
- },
895
-
896
- detect: function(klass) {
897
- return klass !== DS.Model && DS.Model.detect(klass);
898
- },
899
-
900
- columnsForType: function(type) {
901
- var columns = [{ name: 'id', desc: 'Id' }], count = 0, self = this;
902
- get(type, 'attributes').forEach(function(name, meta) {
903
- if (count++ > self.attributeLimit) { return false; }
904
- var desc = capitalize(underscore(name).replace('_', ' '));
905
- columns.push({ name: name, desc: desc });
906
- });
907
- return columns;
908
- },
877
+ /*
878
+ @method deleteLoadedFixture
879
+ @private
880
+ @param type
881
+ @param record
882
+ */
883
+ deleteLoadedFixture: function(type, record) {
884
+ var existingFixture = this.findExistingFixture(type, record);
885
+
886
+ if(existingFixture) {
887
+ var index = indexOf(type.FIXTURES, existingFixture);
888
+ type.FIXTURES.splice(index, 1);
889
+ return true;
890
+ }
891
+ },
909
892
 
910
- getRecords: function(type) {
911
- return this.get('store').all(type);
912
- },
893
+ /*
894
+ @method findExistingFixture
895
+ @private
896
+ @param type
897
+ @param record
898
+ */
899
+ findExistingFixture: function(type, record) {
900
+ var fixtures = this.fixturesForType(type);
901
+ var id = get(record, 'id');
902
+
903
+ return this.findFixtureById(fixtures, id);
904
+ },
913
905
 
914
- getRecordColumnValues: function(record) {
915
- var self = this, count = 0,
916
- columnValues = { id: get(record, 'id') };
906
+ /*
907
+ @method findFixtureById
908
+ @private
909
+ @param fixtures
910
+ @param id
911
+ */
912
+ findFixtureById: function(fixtures, id) {
913
+ return Ember.A(fixtures).find(function(r) {
914
+ if(''+get(r, 'id') === ''+id) {
915
+ return true;
916
+ } else {
917
+ return false;
918
+ }
919
+ });
920
+ },
917
921
 
918
- record.eachAttribute(function(key) {
919
- if (count++ > self.attributeLimit) {
920
- return false;
922
+ /*
923
+ @method simulateRemoteCall
924
+ @private
925
+ @param callback
926
+ @param context
927
+ */
928
+ simulateRemoteCall: function(callback, context) {
929
+ var adapter = this;
930
+
931
+ return new Ember.RSVP.Promise(function(resolve) {
932
+ if (get(adapter, 'simulateRemoteResponse')) {
933
+ // Schedule with setTimeout
934
+ Ember.run.later(function() {
935
+ resolve(callback.call(context));
936
+ }, get(adapter, 'latency'));
937
+ } else {
938
+ // Asynchronous, but at the of the runloop with zero latency
939
+ Ember.run.schedule('actions', null, function() {
940
+ resolve(callback.call(context));
941
+ });
942
+ }
943
+ }, "DS: FixtureAdapter#simulateRemoteCall");
921
944
  }
922
- var value = get(record, key);
923
- columnValues[key] = value;
924
945
  });
925
- return columnValues;
926
- },
927
946
 
928
- getRecordKeywords: function(record) {
929
- var keywords = [], keys = Ember.A(['id']);
930
- record.eachAttribute(function(key) {
931
- keys.push(key);
932
- });
933
- keys.forEach(function(key) {
934
- keywords.push(get(record, key));
935
- });
936
- return keywords;
937
- },
938
-
939
- getRecordFilterValues: function(record) {
940
- return {
941
- isNew: record.get('isNew'),
942
- isModified: record.get('isDirty') && !record.get('isNew'),
943
- isClean: !record.get('isDirty')
944
- };
945
- },
946
-
947
- getRecordColor: function(record) {
948
- var color = 'black';
949
- if (record.get('isNew')) {
950
- color = 'green';
951
- } else if (record.get('isDirty')) {
952
- color = 'blue';
953
- }
954
- return color;
955
- },
947
+ __exports__["default"] = FixtureAdapter;
948
+ });
949
+ define("ember-data/lib/adapters/rest_adapter",
950
+ ["../system/adapter","exports"],
951
+ function(__dependency1__, __exports__) {
952
+ "use strict";
953
+ /**
954
+ @module ember-data
955
+ */
956
956
 
957
- observeRecord: function(record, recordUpdated) {
958
- var releaseMethods = Ember.A(), self = this,
959
- keysToObserve = Ember.A(['id', 'isNew', 'isDirty']);
957
+ var Adapter = __dependency1__["default"];
958
+ var get = Ember.get, set = Ember.set;
959
+ var forEach = Ember.ArrayPolyfills.forEach;
960
960
 
961
- record.eachAttribute(function(key) {
962
- keysToObserve.push(key);
963
- });
961
+ /**
962
+ The REST adapter allows your store to communicate with an HTTP server by
963
+ transmitting JSON via XHR. Most Ember.js apps that consume a JSON API
964
+ should use the REST adapter.
964
965
 
965
- keysToObserve.forEach(function(key) {
966
- var handler = function() {
967
- recordUpdated(self.wrapRecord(record));
968
- };
969
- Ember.addObserver(record, key, handler);
970
- releaseMethods.push(function() {
971
- Ember.removeObserver(record, key, handler);
972
- });
973
- });
966
+ This adapter is designed around the idea that the JSON exchanged with
967
+ the server should be conventional.
974
968
 
975
- var release = function() {
976
- releaseMethods.forEach(function(fn) { fn(); } );
977
- };
969
+ ## JSON Structure
978
970
 
979
- return release;
980
- }
971
+ The REST adapter expects the JSON returned from your server to follow
972
+ these conventions.
981
973
 
982
- });
974
+ ### Object Root
983
975
 
984
- })();
976
+ The JSON payload should be an object that contains the record inside a
977
+ root property. For example, in response to a `GET` request for
978
+ `/posts/1`, the JSON should look like this:
985
979
 
980
+ ```js
981
+ {
982
+ "post": {
983
+ "title": "I'm Running to Reform the W3C's Tag",
984
+ "author": "Yehuda Katz"
985
+ }
986
+ }
987
+ ```
986
988
 
989
+ ### Conventional Names
987
990
 
988
- (function() {
989
- /**
990
- The `DS.Transform` class is used to serialize and deserialize model
991
- attributes when they are saved or loaded from an
992
- adapter. Subclassing `DS.Transform` is useful for creating custom
993
- attributes. All subclasses of `DS.Transform` must implement a
994
- `serialize` and a `deserialize` method.
995
-
996
- Example
997
-
998
- ```javascript
999
- App.RawTransform = DS.Transform.extend({
1000
- deserialize: function(serialized) {
1001
- return serialized;
1002
- },
1003
- serialize: function(deserialized) {
1004
- return deserialized;
1005
- }
1006
- });
1007
- ```
991
+ Attribute names in your JSON payload should be the camelCased versions of
992
+ the attributes in your Ember.js models.
1008
993
 
1009
- Usage
994
+ For example, if you have a `Person` model:
1010
995
 
1011
- ```javascript
1012
- var attr = DS.attr;
1013
- App.Requirement = DS.Model.extend({
1014
- name: attr('string'),
1015
- optionsArray: attr('raw')
1016
- });
1017
- ```
996
+ ```js
997
+ App.Person = DS.Model.extend({
998
+ firstName: DS.attr('string'),
999
+ lastName: DS.attr('string'),
1000
+ occupation: DS.attr('string')
1001
+ });
1002
+ ```
1018
1003
 
1019
- @class Transform
1020
- @namespace DS
1021
- */
1022
- DS.Transform = Ember.Object.extend({
1023
- /**
1024
- When given a deserialized value from a record attribute this
1025
- method must return the serialized value.
1004
+ The JSON returned should look like this:
1026
1005
 
1027
- Example
1006
+ ```js
1007
+ {
1008
+ "person": {
1009
+ "firstName": "Barack",
1010
+ "lastName": "Obama",
1011
+ "occupation": "President"
1012
+ }
1013
+ }
1014
+ ```
1028
1015
 
1029
- ```javascript
1030
- serialize: function(deserialized) {
1031
- return Ember.isEmpty(deserialized) ? null : Number(deserialized);
1032
- }
1033
- ```
1016
+ ## Customization
1034
1017
 
1035
- @method serialize
1036
- @param deserialized The deserialized value
1037
- @return The serialized value
1038
- */
1039
- serialize: Ember.required(),
1018
+ ### Endpoint path customization
1040
1019
 
1041
- /**
1042
- When given a serialize value from a JSON object this method must
1043
- return the deserialized value for the record attribute.
1020
+ Endpoint paths can be prefixed with a `namespace` by setting the namespace
1021
+ property on the adapter:
1044
1022
 
1045
- Example
1023
+ ```js
1024
+ DS.RESTAdapter.reopen({
1025
+ namespace: 'api/1'
1026
+ });
1027
+ ```
1028
+ Requests for `App.Person` would now target `/api/1/people/1`.
1046
1029
 
1047
- ```javascript
1048
- deserialize: function(serialized) {
1049
- return empty(serialized) ? null : Number(serialized);
1050
- }
1051
- ```
1030
+ ### Host customization
1052
1031
 
1053
- @method deserialize
1054
- @param serialized The serialized value
1055
- @return The deserialized value
1056
- */
1057
- deserialize: Ember.required()
1032
+ An adapter can target other hosts by setting the `host` property.
1058
1033
 
1059
- });
1034
+ ```js
1035
+ DS.RESTAdapter.reopen({
1036
+ host: 'https://api.example.com'
1037
+ });
1038
+ ```
1060
1039
 
1061
- })();
1040
+ ### Headers customization
1062
1041
 
1042
+ Some APIs require HTTP headers, e.g. to provide an API key. An array of
1043
+ headers can be added to the adapter which are passed with every request:
1063
1044
 
1045
+ ```js
1046
+ DS.RESTAdapter.reopen({
1047
+ headers: {
1048
+ "API_KEY": "secret key",
1049
+ "ANOTHER_HEADER": "Some header value"
1050
+ }
1051
+ });
1052
+ ```
1053
+
1054
+ @class RESTAdapter
1055
+ @constructor
1056
+ @namespace DS
1057
+ @extends DS.Adapter
1058
+ */
1059
+ var RESTAdapter = Adapter.extend({
1060
+ defaultSerializer: '-rest',
1061
+ /**
1062
+ Endpoint paths can be prefixed with a `namespace` by setting the namespace
1063
+ property on the adapter:
1064
+
1065
+ ```javascript
1066
+ DS.RESTAdapter.reopen({
1067
+ namespace: 'api/1'
1068
+ });
1069
+ ```
1064
1070
 
1065
- (function() {
1071
+ Requests for `App.Post` would now target `/api/1/post/`.
1066
1072
 
1067
- /**
1068
- The `DS.BooleanTransform` class is used to serialize and deserialize
1069
- boolean attributes on Ember Data record objects. This transform is
1070
- used when `boolean` is passed as the type parameter to the
1071
- [DS.attr](../../data#method_attr) function.
1073
+ @property namespace
1074
+ @type {String}
1075
+ */
1072
1076
 
1073
- Usage
1077
+ /**
1078
+ An adapter can target other hosts by setting the `host` property.
1074
1079
 
1075
- ```javascript
1076
- var attr = DS.attr;
1077
- App.User = DS.Model.extend({
1078
- isAdmin: attr('boolean'),
1079
- name: attr('string'),
1080
- email: attr('string')
1081
- });
1082
- ```
1080
+ ```javascript
1081
+ DS.RESTAdapter.reopen({
1082
+ host: 'https://api.example.com'
1083
+ });
1084
+ ```
1083
1085
 
1084
- @class BooleanTransform
1085
- @extends DS.Transform
1086
- @namespace DS
1087
- */
1088
- DS.BooleanTransform = DS.Transform.extend({
1089
- deserialize: function(serialized) {
1090
- var type = typeof serialized;
1091
-
1092
- if (type === "boolean") {
1093
- return serialized;
1094
- } else if (type === "string") {
1095
- return serialized.match(/^true$|^t$|^1$/i) !== null;
1096
- } else if (type === "number") {
1097
- return serialized === 1;
1098
- } else {
1099
- return false;
1100
- }
1101
- },
1086
+ Requests for `App.Post` would now target `https://api.example.com/post/`.
1102
1087
 
1103
- serialize: function(deserialized) {
1104
- return Boolean(deserialized);
1105
- }
1106
- });
1088
+ @property host
1089
+ @type {String}
1090
+ */
1107
1091
 
1108
- })();
1092
+ /**
1093
+ Some APIs require HTTP headers, e.g. to provide an API key. An array of
1094
+ headers can be added to the adapter which are passed with every request:
1109
1095
 
1096
+ ```javascript
1097
+ DS.RESTAdapter.reopen({
1098
+ headers: {
1099
+ "API_KEY": "secret key",
1100
+ "ANOTHER_HEADER": "Some header value"
1101
+ }
1102
+ });
1103
+ ```
1110
1104
 
1105
+ @property headers
1106
+ @type {Object}
1107
+ */
1111
1108
 
1112
- (function() {
1113
- /**
1114
- The `DS.DateTransform` class is used to serialize and deserialize
1115
- date attributes on Ember Data record objects. This transform is used
1116
- when `date` is passed as the type parameter to the
1117
- [DS.attr](../../data#method_attr) function.
1118
-
1119
- ```javascript
1120
- var attr = DS.attr;
1121
- App.Score = DS.Model.extend({
1122
- value: attr('number'),
1123
- player: DS.belongsTo('player'),
1124
- date: attr('date')
1125
- });
1126
- ```
1109
+ /**
1110
+ Called by the store in order to fetch the JSON for a given
1111
+ type and ID.
1127
1112
 
1128
- @class DateTransform
1129
- @extends DS.Transform
1130
- @namespace DS
1131
- */
1132
- DS.DateTransform = DS.Transform.extend({
1133
-
1134
- deserialize: function(serialized) {
1135
- var type = typeof serialized;
1136
-
1137
- if (type === "string") {
1138
- return new Date(Ember.Date.parse(serialized));
1139
- } else if (type === "number") {
1140
- return new Date(serialized);
1141
- } else if (serialized === null || serialized === undefined) {
1142
- // if the value is not present in the data,
1143
- // return undefined, not null.
1144
- return serialized;
1145
- } else {
1146
- return null;
1147
- }
1148
- },
1149
-
1150
- serialize: function(date) {
1151
- if (date instanceof Date) {
1152
- // Serialize it as a number to maintain millisecond precision
1153
- return Number(date);
1154
- } else {
1155
- return null;
1156
- }
1157
- }
1113
+ The `find` method makes an Ajax request to a URL computed by `buildURL`, and returns a
1114
+ promise for the resulting payload.
1158
1115
 
1159
- });
1116
+ This method performs an HTTP `GET` request with the id provided as part of the query string.
1160
1117
 
1161
- })();
1118
+ @method find
1119
+ @param {DS.Store} store
1120
+ @param {subclass of DS.Model} type
1121
+ @param {String} id
1122
+ @returns {Promise} promise
1123
+ */
1124
+ find: function(store, type, id) {
1125
+ return this.ajax(this.buildURL(type.typeKey, id), 'GET');
1126
+ },
1162
1127
 
1128
+ /**
1129
+ Called by the store in order to fetch a JSON array for all
1130
+ of the records for a given type.
1163
1131
 
1132
+ The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
1133
+ promise for the resulting payload.
1164
1134
 
1165
- (function() {
1166
- var empty = Ember.isEmpty;
1167
- /**
1168
- The `DS.NumberTransform` class is used to serialize and deserialize
1169
- numeric attributes on Ember Data record objects. This transform is
1170
- used when `number` is passed as the type parameter to the
1171
- [DS.attr](../../data#method_attr) function.
1172
-
1173
- Usage
1174
-
1175
- ```javascript
1176
- var attr = DS.attr;
1177
- App.Score = DS.Model.extend({
1178
- value: attr('number'),
1179
- player: DS.belongsTo('player'),
1180
- date: attr('date')
1181
- });
1182
- ```
1135
+ @private
1136
+ @method findAll
1137
+ @param {DS.Store} store
1138
+ @param {subclass of DS.Model} type
1139
+ @param {String} sinceToken
1140
+ @returns {Promise} promise
1141
+ */
1142
+ findAll: function(store, type, sinceToken) {
1143
+ var query;
1183
1144
 
1184
- @class NumberTransform
1185
- @extends DS.Transform
1186
- @namespace DS
1187
- */
1188
- DS.NumberTransform = DS.Transform.extend({
1145
+ if (sinceToken) {
1146
+ query = { since: sinceToken };
1147
+ }
1189
1148
 
1190
- deserialize: function(serialized) {
1191
- return empty(serialized) ? null : Number(serialized);
1192
- },
1149
+ return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
1150
+ },
1193
1151
 
1194
- serialize: function(deserialized) {
1195
- return empty(deserialized) ? null : Number(deserialized);
1196
- }
1197
- });
1152
+ /**
1153
+ Called by the store in order to fetch a JSON array for
1154
+ the records that match a particular query.
1198
1155
 
1199
- })();
1156
+ The `findQuery` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
1157
+ promise for the resulting payload.
1200
1158
 
1159
+ The `query` argument is a simple JavaScript object that will be passed directly
1160
+ to the server as parameters.
1201
1161
 
1162
+ @private
1163
+ @method findQuery
1164
+ @param {DS.Store} store
1165
+ @param {subclass of DS.Model} type
1166
+ @param {Object} query
1167
+ @returns {Promise} promise
1168
+ */
1169
+ findQuery: function(store, type, query) {
1170
+ return this.ajax(this.buildURL(type.typeKey), 'GET', { data: query });
1171
+ },
1202
1172
 
1203
- (function() {
1204
- var none = Ember.isNone;
1205
-
1206
- /**
1207
- The `DS.StringTransform` class is used to serialize and deserialize
1208
- string attributes on Ember Data record objects. This transform is
1209
- used when `string` is passed as the type parameter to the
1210
- [DS.attr](../../data#method_attr) function.
1211
-
1212
- Usage
1213
-
1214
- ```javascript
1215
- var attr = DS.attr;
1216
- App.User = DS.Model.extend({
1217
- isAdmin: attr('boolean'),
1218
- name: attr('string'),
1219
- email: attr('string')
1220
- });
1221
- ```
1173
+ /**
1174
+ Called by the store in order to fetch a JSON array for
1175
+ the unloaded records in a has-many relationship that were originally
1176
+ specified as IDs.
1222
1177
 
1223
- @class StringTransform
1224
- @extends DS.Transform
1225
- @namespace DS
1226
- */
1227
- DS.StringTransform = DS.Transform.extend({
1178
+ For example, if the original payload looks like:
1228
1179
 
1229
- deserialize: function(serialized) {
1230
- return none(serialized) ? null : String(serialized);
1231
- },
1180
+ ```js
1181
+ {
1182
+ "id": 1,
1183
+ "title": "Rails is omakase",
1184
+ "comments": [ 1, 2, 3 ]
1185
+ }
1186
+ ```
1232
1187
 
1233
- serialize: function(deserialized) {
1234
- return none(deserialized) ? null : String(deserialized);
1235
- }
1188
+ The IDs will be passed as a URL-encoded Array of IDs, in this form:
1236
1189
 
1237
- });
1190
+ ```
1191
+ ids[]=1&ids[]=2&ids[]=3
1192
+ ```
1238
1193
 
1239
- })();
1194
+ Many servers, such as Rails and PHP, will automatically convert this URL-encoded array
1195
+ into an Array for you on the server-side. If you want to encode the
1196
+ IDs, differently, just override this (one-line) method.
1240
1197
 
1198
+ The `findMany` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
1199
+ promise for the resulting payload.
1241
1200
 
1201
+ @method findMany
1202
+ @param {DS.Store} store
1203
+ @param {subclass of DS.Model} type
1204
+ @param {Array} ids
1205
+ @returns {Promise} promise
1206
+ */
1207
+ findMany: function(store, type, ids) {
1208
+ return this.ajax(this.buildURL(type.typeKey), 'GET', { data: { ids: ids } });
1209
+ },
1242
1210
 
1243
- (function() {
1211
+ /**
1212
+ Called by the store in order to fetch a JSON array for
1213
+ the unloaded records in a has-many relationship that were originally
1214
+ specified as a URL (inside of `links`).
1244
1215
 
1245
- })();
1216
+ For example, if your original payload looks like this:
1246
1217
 
1218
+ ```js
1219
+ {
1220
+ "post": {
1221
+ "id": 1,
1222
+ "title": "Rails is omakase",
1223
+ "links": { "comments": "/posts/1/comments" }
1224
+ }
1225
+ }
1226
+ ```
1227
+
1228
+ This method will be called with the parent record and `/posts/1/comments`.
1229
+
1230
+ The `findHasMany` method will make an Ajax (HTTP GET) request to the originally specified URL.
1231
+ If the URL is host-relative (starting with a single slash), the
1232
+ request will use the host specified on the adapter (if any).
1233
+
1234
+ @method findHasMany
1235
+ @param {DS.Store} store
1236
+ @param {DS.Model} record
1237
+ @param {String} url
1238
+ @returns {Promise} promise
1239
+ */
1240
+ findHasMany: function(store, record, url) {
1241
+ var host = get(this, 'host'),
1242
+ id = get(record, 'id'),
1243
+ type = record.constructor.typeKey;
1244
+
1245
+ if (host && url.charAt(0) === '/' && url.charAt(1) !== '/') {
1246
+ url = host + url;
1247
+ }
1247
1248
 
1249
+ return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
1250
+ },
1248
1251
 
1249
- (function() {
1250
- /**
1251
- @module ember-data
1252
- */
1253
-
1254
- var set = Ember.set;
1252
+ /**
1253
+ Called by the store in order to fetch a JSON array for
1254
+ the unloaded records in a belongs-to relationship that were originally
1255
+ specified as a URL (inside of `links`).
1255
1256
 
1256
- /*
1257
- This code registers an injection for Ember.Application.
1257
+ For example, if your original payload looks like this:
1258
1258
 
1259
- If an Ember.js developer defines a subclass of DS.Store on their application,
1260
- this code will automatically instantiate it and make it available on the
1261
- router.
1259
+ ```js
1260
+ {
1261
+ "person": {
1262
+ "id": 1,
1263
+ "name": "Tom Dale",
1264
+ "links": { "group": "/people/1/group" }
1265
+ }
1266
+ }
1267
+ ```
1262
1268
 
1263
- Additionally, after an application's controllers have been injected, they will
1264
- each have the store made available to them.
1269
+ This method will be called with the parent record and `/people/1/group`.
1265
1270
 
1266
- For example, imagine an Ember.js application with the following classes:
1271
+ The `findBelongsTo` method will make an Ajax (HTTP GET) request to the originally specified URL.
1267
1272
 
1268
- App.Store = DS.Store.extend({
1269
- adapter: 'custom'
1270
- });
1273
+ @method findBelongsTo
1274
+ @param {DS.Store} store
1275
+ @param {DS.Model} record
1276
+ @param {String} url
1277
+ @returns {Promise} promise
1278
+ */
1279
+ findBelongsTo: function(store, record, url) {
1280
+ var id = get(record, 'id'),
1281
+ type = record.constructor.typeKey;
1271
1282
 
1272
- App.PostsController = Ember.ArrayController.extend({
1273
- // ...
1274
- });
1283
+ return this.ajax(this.urlPrefix(url, this.buildURL(type, id)), 'GET');
1284
+ },
1275
1285
 
1276
- When the application is initialized, `App.Store` will automatically be
1277
- instantiated, and the instance of `App.PostsController` will have its `store`
1278
- property set to that instance.
1286
+ /**
1287
+ Called by the store when a newly created record is
1288
+ saved via the `save` method on a model record instance.
1279
1289
 
1280
- Note that this code will only be run if the `ember-application` package is
1281
- loaded. If Ember Data is being used in an environment other than a
1282
- typical application (e.g., node.js where only `ember-runtime` is available),
1283
- this code will be ignored.
1284
- */
1290
+ The `createRecord` method serializes the record and makes an Ajax (HTTP POST) request
1291
+ to a URL computed by `buildURL`.
1285
1292
 
1286
- Ember.onLoad('Ember.Application', function(Application) {
1287
- Application.initializer({
1288
- name: "store",
1293
+ See `serialize` for information on how to customize the serialized form
1294
+ of a record.
1289
1295
 
1290
- initialize: function(container, application) {
1291
- application.register('store:main', application.Store || DS.Store);
1296
+ @method createRecord
1297
+ @param {DS.Store} store
1298
+ @param {subclass of DS.Model} type
1299
+ @param {DS.Model} record
1300
+ @returns {Promise} promise
1301
+ */
1302
+ createRecord: function(store, type, record) {
1303
+ var data = {};
1304
+ var serializer = store.serializerFor(type.typeKey);
1292
1305
 
1293
- // allow older names to be looked up
1306
+ serializer.serializeIntoHash(data, type, record, { includeId: true });
1294
1307
 
1295
- var proxy = new DS.ContainerProxy(container);
1296
- proxy.registerDeprecations([
1297
- {deprecated: 'serializer:_default', valid: 'serializer:-default'},
1298
- {deprecated: 'serializer:_rest', valid: 'serializer:-rest'},
1299
- {deprecated: 'adapter:_rest', valid: 'adapter:-rest'}
1300
- ]);
1308
+ return this.ajax(this.buildURL(type.typeKey), "POST", { data: data });
1309
+ },
1301
1310
 
1302
- // new go forward paths
1303
- application.register('serializer:-default', DS.JSONSerializer);
1304
- application.register('serializer:-rest', DS.RESTSerializer);
1305
- application.register('adapter:-rest', DS.RESTAdapter);
1311
+ /**
1312
+ Called by the store when an existing record is saved
1313
+ via the `save` method on a model record instance.
1306
1314
 
1307
- // Eagerly generate the store so defaultStore is populated.
1308
- // TODO: Do this in a finisher hook
1309
- container.lookup('store:main');
1310
- }
1311
- });
1315
+ The `updateRecord` method serializes the record and makes an Ajax (HTTP PUT) request
1316
+ to a URL computed by `buildURL`.
1312
1317
 
1313
- Application.initializer({
1314
- name: "transforms",
1315
- before: "store",
1318
+ See `serialize` for information on how to customize the serialized form
1319
+ of a record.
1316
1320
 
1317
- initialize: function(container, application) {
1318
- application.register('transform:boolean', DS.BooleanTransform);
1319
- application.register('transform:date', DS.DateTransform);
1320
- application.register('transform:number', DS.NumberTransform);