ember-data-source 2.1.0.beta.2 → 2.1.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
data/dist/ember-data.js CHANGED
@@ -340,10 +340,7 @@
340
340
  */
341
341
 
342
342
  function ember$data$lib$adapters$errors$$InvalidError(errors) {
343
- if (!Ember.isArray(errors)) {
344
- Ember.deprecate('`InvalidError` expects json-api formatted errors.', false, { id: 'ds.errors.invalid-error-expects-json-api-format', until: '2.0.0' });
345
- errors = ember$data$lib$adapters$errors$$errorsHashToArray(errors);
346
- }
343
+ Ember.assert('`InvalidError` expects json-api formatted errors array.', Ember.isArray(errors || []));
347
344
  ember$data$lib$adapters$errors$$AdapterError.call(this, errors, 'The adapter rejected the commit because it was invalid');
348
345
  }
349
346
 
@@ -953,6 +950,12 @@
953
950
  }
954
951
  ```
955
952
 
953
+ Note that the object root can be pluralized for both a single-object response
954
+ and an array response: the REST adapter is not strict on this. Further, if the
955
+ HTTP server responds to a `GET` request to `/posts/1` (e.g. the response to a
956
+ `findRecord` query) with more than one object in the array, Ember Data will
957
+ only display the object with the matching ID.
958
+
956
959
  ### Conventional Names
957
960
 
958
961
  Attribute names in your JSON payload should be the camelCased versions of
@@ -1227,8 +1230,7 @@
1227
1230
  of the records for a given type.
1228
1231
  The `findAll` method makes an Ajax (HTTP GET) request to a URL computed by `buildURL`, and returns a
1229
1232
  promise for the resulting payload.
1230
- @private
1231
- @method findAll
1233
+ @method findAll
1232
1234
  @param {DS.Store} store
1233
1235
  @param {DS.Model} type
1234
1236
  @param {String} sinceToken
@@ -1254,8 +1256,7 @@
1254
1256
  payload.
1255
1257
  The `query` argument is a simple JavaScript object that will be passed directly
1256
1258
  to the server as parameters.
1257
- @private
1258
- @method query
1259
+ @method query
1259
1260
  @param {DS.Store} store
1260
1261
  @param {DS.Model} type
1261
1262
  @param {Object} query
@@ -1279,8 +1280,7 @@
1279
1280
  payload.
1280
1281
  The `query` argument is a simple JavaScript object that will be passed directly
1281
1282
  to the server as parameters.
1282
- @private
1283
- @method queryRecord
1283
+ @method queryRecord
1284
1284
  @param {DS.Store} store
1285
1285
  @param {DS.Model} type
1286
1286
  @param {Object} query
@@ -1788,6 +1788,44 @@
1788
1788
  return hash;
1789
1789
  },
1790
1790
 
1791
+ /**
1792
+ By default the JSONAPIAdapter will send each find request coming from a `store.find`
1793
+ or from accessing a relationship separately to the server. If your server supports passing
1794
+ ids as a query string, you can set coalesceFindRequests to true to coalesce all find requests
1795
+ within a single runloop.
1796
+ For example, if you have an initial payload of:
1797
+ ```javascript
1798
+ {
1799
+ post: {
1800
+ id: 1,
1801
+ comments: [1, 2]
1802
+ }
1803
+ }
1804
+ ```
1805
+ By default calling `post.get('comments')` will trigger the following requests(assuming the
1806
+ comments haven't been loaded before):
1807
+ ```
1808
+ GET /comments/1
1809
+ GET /comments/2
1810
+ ```
1811
+ If you set coalesceFindRequests to `true` it will instead trigger the following request:
1812
+ ```
1813
+ GET /comments?filter[id]=1,2
1814
+ ```
1815
+ Setting coalesceFindRequests to `true` also works for `store.find` requests and `belongsTo`
1816
+ relationships accessed within the same runloop. If you set `coalesceFindRequests: true`
1817
+ ```javascript
1818
+ store.findRecord('comment', 1);
1819
+ store.findRecord('comment', 2);
1820
+ ```
1821
+ will also send a request to: `GET /comments?filter[id]=1,2`
1822
+ Note: Requests coalescing rely on URL building strategy. So if you override `buildURL` in your app
1823
+ `groupRecordsForFindMany` more likely should be overridden as well in order for coalescing to work.
1824
+ @property coalesceFindRequests
1825
+ @type {boolean}
1826
+ */
1827
+ coalesceFindRequests: false,
1828
+
1791
1829
  /**
1792
1830
  @method findMany
1793
1831
  @param {DS.Store} store
@@ -1833,7 +1871,7 @@
1833
1871
  });
1834
1872
 
1835
1873
  var ember$data$lib$core$$DS = Ember.Namespace.create({
1836
- VERSION: '2.1.0-beta.2'
1874
+ VERSION: '2.1.0-beta.3'
1837
1875
  });
1838
1876
 
1839
1877
  if (Ember.libraries) {
@@ -1846,6 +1884,28 @@
1846
1884
  Ember.merge(Ember.FEATURES, ember$data$lib$core$$EMBER_DATA_FEATURES);
1847
1885
 
1848
1886
  var ember$data$lib$core$$default = ember$data$lib$core$$DS;
1887
+ var ember$data$lib$system$normalize$link$$default = ember$data$lib$system$normalize$link$$_normalizeLink;
1888
+ /**
1889
+ This method normalizes a link to an "links object". If the passed link is
1890
+ already an object it's returned without any modifications.
1891
+
1892
+ See http://jsonapi.org/format/#document-links for more information.
1893
+
1894
+ @method _normalizeLink
1895
+ @private
1896
+ @param {String} link
1897
+ @return {Object|null}
1898
+ @for DS
1899
+ */
1900
+ function ember$data$lib$system$normalize$link$$_normalizeLink(link) {
1901
+ switch (typeof link) {
1902
+ case 'object':
1903
+ return link;
1904
+ case 'string':
1905
+ return { href: link };
1906
+ }
1907
+ return null;
1908
+ }
1849
1909
  var ember$data$lib$system$normalize$model$name$$default = ember$data$lib$system$normalize$model$name$$normalizeModelName;
1850
1910
  /**
1851
1911
  All modelNames are dasherized internally. Changing this function may
@@ -3115,7 +3175,7 @@
3115
3175
 
3116
3176
  var ember$data$lib$system$store$serializer$response$$get = Ember.get;
3117
3177
 
3118
- /**
3178
+ /*
3119
3179
  This is a helper method that validates a JSON API top-level document
3120
3180
 
3121
3181
  The format of a document is described here:
@@ -3173,7 +3233,7 @@
3173
3233
  return errors;
3174
3234
  }
3175
3235
 
3176
- /**
3236
+ /*
3177
3237
  This is a helper method that always returns a JSON-API Document.
3178
3238
 
3179
3239
  @method normalizeResponseHelper
@@ -3201,7 +3261,7 @@
3201
3261
  return normalizedResponse;
3202
3262
  }
3203
3263
 
3204
- /**
3264
+ /*
3205
3265
  Convert the payload from `serializer.extract` to a JSON-API Document.
3206
3266
 
3207
3267
  @method _normalizeSerializerPayload
@@ -3227,7 +3287,7 @@
3227
3287
  return { data: data };
3228
3288
  }
3229
3289
 
3230
- /**
3290
+ /*
3231
3291
  Convert the payload representing a single record from `serializer.extract` to
3232
3292
  a JSON-API Resource Object.
3233
3293
 
@@ -3313,7 +3373,7 @@
3313
3373
  return { id: '' + value, type: relationshipMeta.type };
3314
3374
  }
3315
3375
 
3316
- /**
3376
+ /*
3317
3377
  This method converts a JSON-API Resource Object to a format that DS.Store
3318
3378
  understands.
3319
3379
 
@@ -5133,6 +5193,7 @@
5133
5193
  this.linkPromise = null;
5134
5194
  this.meta = null;
5135
5195
  this.hasData = false;
5196
+ this.hasLoaded = false;
5136
5197
  }
5137
5198
 
5138
5199
  ember$data$lib$system$relationships$state$relationship$$Relationship.prototype = {
@@ -5317,6 +5378,7 @@
5317
5378
  if (link !== this.link) {
5318
5379
  this.link = link;
5319
5380
  this.linkPromise = null;
5381
+ this.setHasLoaded(false);
5320
5382
  this.record.notifyPropertyChange(this.key);
5321
5383
  }
5322
5384
  },
@@ -5338,13 +5400,35 @@
5338
5400
  //TODO Once we have adapter support, we need to handle updated and canonical changes
5339
5401
  this.computeChanges(records);
5340
5402
  this.setHasData(true);
5403
+ this.setHasLoaded(true);
5341
5404
  },
5342
5405
 
5343
5406
  notifyRecordRelationshipAdded: Ember.K,
5344
5407
  notifyRecordRelationshipRemoved: Ember.K,
5345
5408
 
5409
+ /*
5410
+ `hasData` for a relationship is a flag to indicate if we consider the
5411
+ content of this relationship "known". Snapshots uses this to tell the
5412
+ difference between unknown (`undefined`) or empty (`null`). The reason for
5413
+ this is that we wouldn't want to serialize unknown relationships as `null`
5414
+ as that might overwrite remote state.
5415
+ All relationships for a newly created (`store.createRecord()`) are
5416
+ considered known (`hasData === true`).
5417
+ */
5346
5418
  setHasData: function (value) {
5347
5419
  this.hasData = value;
5420
+ },
5421
+
5422
+ /*
5423
+ `hasLoaded` is a flag to indicate if we have gotten data from the adapter or
5424
+ not when the relationship has a link.
5425
+ This is used to be able to tell when to fetch the link and when to return
5426
+ the local data in scenarios where the local state is considered known
5427
+ (`hasData === true`).
5428
+ Updating the link will automatically set `hasLoaded` to `false`.
5429
+ */
5430
+ setHasLoaded: function (value) {
5431
+ this.hasLoaded = value;
5348
5432
  }
5349
5433
  };
5350
5434
 
@@ -5791,9 +5875,13 @@
5791
5875
  if (this.isAsync) {
5792
5876
  var promise;
5793
5877
  if (this.link) {
5794
- promise = this.findLink().then(function () {
5795
- return _this3.findRecords();
5796
- });
5878
+ if (this.hasLoaded) {
5879
+ promise = this.findRecords();
5880
+ } else {
5881
+ promise = this.findLink().then(function () {
5882
+ return _this3.findRecords();
5883
+ });
5884
+ }
5797
5885
  } else {
5798
5886
  promise = this.findRecords();
5799
5887
  }
@@ -5843,6 +5931,7 @@
5843
5931
  this.removeRecord(this.inverseRecord);
5844
5932
  }
5845
5933
  this.setHasData(true);
5934
+ this.setHasLoaded(true);
5846
5935
  };
5847
5936
 
5848
5937
  ember$data$lib$system$relationships$state$belongs$to$$BelongsToRelationship.prototype.setCanonicalRecord = function (newRecord) {
@@ -5852,6 +5941,7 @@
5852
5941
  this.removeCanonicalRecord(this.inverseRecord);
5853
5942
  }
5854
5943
  this.setHasData(true);
5944
+ this.setHasLoaded(true);
5855
5945
  };
5856
5946
 
5857
5947
  ember$data$lib$system$relationships$state$belongs$to$$BelongsToRelationship.prototype._super$addCanonicalRecord = ember$data$lib$system$relationships$state$relationship$$default.prototype.addCanonicalRecord;
@@ -5948,9 +6038,13 @@
5948
6038
  if (this.isAsync) {
5949
6039
  var promise;
5950
6040
  if (this.link) {
5951
- promise = this.findLink().then(function () {
5952
- return _this2.findRecord();
5953
- });
6041
+ if (this.hasLoaded) {
6042
+ promise = this.findRecord();
6043
+ } else {
6044
+ promise = this.findLink().then(function () {
6045
+ return _this2.findRecord();
6046
+ });
6047
+ }
5954
6048
  } else {
5955
6049
  promise = this.findRecord();
5956
6050
  }
@@ -7143,10 +7237,10 @@
7143
7237
  automatically created by their `Ember.Application`.
7144
7238
 
7145
7239
  You can retrieve models from the store in several ways. To retrieve a record
7146
- for a specific id, use `DS.Store`'s `find()` method:
7240
+ for a specific id, use `DS.Store`'s `findRecord()` method:
7147
7241
 
7148
7242
  ```javascript
7149
- store.find('person', 123).then(function (person) {
7243
+ store.findRecord('person', 123).then(function (person) {
7150
7244
  });
7151
7245
  ```
7152
7246
 
@@ -8083,11 +8177,7 @@
8083
8177
  Ember.assert('Passing classes to store methods has been removed. Please pass a dasherized string instead of ' + Ember.inspect(modelName), typeof modelName === 'string');
8084
8178
 
8085
8179
  if (!Ember.ENV.ENABLE_DS_FILTER) {
8086
- Ember.deprecate('The filter API will be moved into a plugin soon. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page', false, {
8087
- url: 'https://github.com/ember-data/ember-data-filter',
8088
- id: 'ds.store.filter-deprecated',
8089
- until: '2.0.0'
8090
- });
8180
+ Ember.assert('The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page. https://github.com/ember-data/ember-data-filter', false);
8091
8181
  }
8092
8182
 
8093
8183
  var promise;
@@ -8579,9 +8669,6 @@
8579
8669
  serializer (the application serializer if it exists).
8580
8670
  Alternatively, `pushPayload` will accept a model type which
8581
8671
  will determine which serializer will process the payload.
8582
- However, the serializer itself (processing this data via
8583
- `normalizePayload`) will not know which model it is
8584
- deserializing.
8585
8672
  ```app/serializers/application.js
8586
8673
  import DS from 'ember-data';
8587
8674
  export default DS.ActiveModelSerializer;
@@ -8721,15 +8808,9 @@
8721
8808
  @param {String} modelName
8722
8809
  @return DS.Adapter
8723
8810
  */
8724
- adapterFor: function (modelOrClass) {
8725
- var modelName;
8811
+ adapterFor: function (modelName) {
8726
8812
 
8727
- if (typeof modelOrClass === 'string') {
8728
- modelName = modelOrClass;
8729
- } else {
8730
- Ember.deprecate("Passing classes to store methods has been removed. Please pass a dasherized string instead of " + Ember.inspect(modelName), false, { id: 'ds.store.passing-classes-deprecated', until: '2.0.0' });
8731
- modelName = modelOrClass.modelName;
8732
- }
8813
+ Ember.assert("Passing classes to store.adapterFor has been removed. Please pass a dasherized string instead of " + Ember.inspect(modelName), typeof modelName === 'string');
8733
8814
 
8734
8815
  return this.lookupAdapter(modelName);
8735
8816
  },
@@ -8759,15 +8840,9 @@
8759
8840
  @param {String} modelName the record to serialize
8760
8841
  @return {DS.Serializer}
8761
8842
  */
8762
- serializerFor: function (modelOrClass) {
8763
- var modelName;
8843
+ serializerFor: function (modelName) {
8764
8844
 
8765
- if (typeof modelOrClass === 'string') {
8766
- modelName = modelOrClass;
8767
- } else {
8768
- Ember.deprecate("Passing classes to store methods has been removed. Please pass a dasherized string instead of " + Ember.inspect(modelName), false, { id: 'ds.store.passing-classes-deprecated', until: '2.0.0' });
8769
- modelName = modelOrClass.modelName;
8770
- }
8845
+ Ember.assert("Passing classes to store.serializerFor has been removed. Please pass a dasherized string instead of " + Ember.inspect(modelName), typeof modelName === 'string');
8771
8846
 
8772
8847
  var fallbacks = ['application', this.adapterFor(modelName).get('defaultSerializer'), '-default'];
8773
8848
 
@@ -8926,8 +9001,11 @@
8926
9001
  var relationship;
8927
9002
 
8928
9003
  if (data.relationships[key].links && data.relationships[key].links.related) {
8929
- relationship = record._relationships.get(key);
8930
- relationship.updateLink(data.relationships[key].links.related);
9004
+ var relatedLink = ember$data$lib$system$normalize$link$$default(data.relationships[key].links.related);
9005
+ if (relatedLink && relatedLink.href) {
9006
+ relationship = record._relationships.get(key);
9007
+ relationship.updateLink(relatedLink.href);
9008
+ }
8931
9009
  }
8932
9010
 
8933
9011
  if (data.relationships[key].meta) {
@@ -9582,7 +9660,7 @@
9582
9660
  if (relationshipMeta.kind === 'belongsTo') {
9583
9661
  data = _this4.extractRelationship(relationshipMeta.type, relationshipHash);
9584
9662
  } else if (relationshipMeta.kind === 'hasMany') {
9585
- data = relationshipHash.map(function (item) {
9663
+ data = Ember.isNone(relationshipHash) ? null : relationshipHash.map(function (item) {
9586
9664
  return _this4.extractRelationship(relationshipMeta.type, item);
9587
9665
  });
9588
9666
  }
@@ -9613,28 +9691,6 @@
9613
9691
  return ember$data$lib$system$normalize$model$name$$default(key);
9614
9692
  },
9615
9693
 
9616
- /**
9617
- You can use this method to normalize all payloads, regardless of whether they
9618
- represent single records or an array.
9619
- For example, you might want to remove some extraneous data from the payload:
9620
- ```app/serializers/application.js
9621
- import DS from 'ember-data';
9622
- export default DS.JSONSerializer.extend({
9623
- normalizePayload: function(payload) {
9624
- delete payload.version;
9625
- delete payload.status;
9626
- return payload;
9627
- }
9628
- });
9629
- ```
9630
- @method normalizePayload
9631
- @param {Object} payload
9632
- @return {Object} the normalized payload
9633
- */
9634
- normalizePayload: function (payload) {
9635
- return payload;
9636
- },
9637
-
9638
9694
  /**
9639
9695
  @method normalizeAttributes
9640
9696
  @private
@@ -10078,16 +10134,18 @@
10078
10134
  var key = relationship.key;
10079
10135
 
10080
10136
  if (this._shouldSerializeHasMany(snapshot, key, relationship)) {
10081
- var payloadKey;
10137
+ var hasMany = snapshot.hasMany(key, { ids: true });
10138
+ if (hasMany !== undefined) {
10139
+ // if provided, use the mapping provided by `attrs` in
10140
+ // the serializer
10141
+ var payloadKey = this._getMappedKey(key);
10142
+ if (payloadKey === key && this.keyForRelationship) {
10143
+ payloadKey = this.keyForRelationship(key, "hasMany", "serialize");
10144
+ }
10082
10145
 
10083
- // if provided, use the mapping provided by `attrs` in
10084
- // the serializer
10085
- payloadKey = this._getMappedKey(key);
10086
- if (payloadKey === key && this.keyForRelationship) {
10087
- payloadKey = this.keyForRelationship(key, "hasMany", "serialize");
10146
+ json[payloadKey] = hasMany;
10147
+ // TODO support for polymorphic manyToNone and manyToMany relationships
10088
10148
  }
10089
- json[payloadKey] = snapshot.hasMany(key, { ids: true });
10090
- // TODO support for polymorphic manyToNone and manyToMany relationships
10091
10149
  }
10092
10150
  },
10093
10151
 
@@ -10588,7 +10646,93 @@
10588
10646
 
10589
10647
  var ember$data$lib$serializers$json$api$serializer$$dasherize = Ember.String.dasherize;
10590
10648
 
10591
- var ember$data$lib$serializers$json$api$serializer$$default = ember$data$lib$serializers$json$serializer$$default.extend({
10649
+ /**
10650
+ Ember Data 2.0 Serializer:
10651
+
10652
+ In Ember Data a Serializer is used to serialize and deserialize
10653
+ records when they are transferred in and out of an external source.
10654
+ This process involves normalizing property names, transforming
10655
+ attribute values and serializing relationships.
10656
+
10657
+ `JSONAPISerializer` supports the http://jsonapi.org/ spec and is the
10658
+ serializer recommended by Ember Data.
10659
+
10660
+ This serializer normalizes a JSON API payload that looks like:
10661
+
10662
+ ```js
10663
+
10664
+ // models/player.js
10665
+ import DS from "ember-data";
10666
+
10667
+ export default DS.Model.extend({
10668
+ name: DS.attr(),
10669
+ skill: DS.attr(),
10670
+ gamesPlayed: DS.attr(),
10671
+ club: DS.belongsTo('club')
10672
+ });
10673
+
10674
+ // models/club.js
10675
+ import DS from "ember-data";
10676
+
10677
+ export default DS.Model.extend({
10678
+ name: DS.attr(),
10679
+ location: DS.attr(),
10680
+ players: DS.hasMany('player')
10681
+ });
10682
+ ```
10683
+
10684
+ ```js
10685
+
10686
+ {
10687
+ "data": [
10688
+ {
10689
+ "attributes": {
10690
+ "name": "Benfica",
10691
+ "location": "Portugal"
10692
+ },
10693
+ "id": "1",
10694
+ "relationships": {
10695
+ "players": {
10696
+ "data": [
10697
+ {
10698
+ "id": "3",
10699
+ "type": "players"
10700
+ }
10701
+ ]
10702
+ }
10703
+ },
10704
+ "type": "clubs"
10705
+ }
10706
+ ],
10707
+ "included": [
10708
+ {
10709
+ "attributes": {
10710
+ "name": "Eusebio Silva Ferreira",
10711
+ "skill": "Rocket shot",
10712
+ "games-played": 431
10713
+ },
10714
+ "id": "3",
10715
+ "relationships": {
10716
+ "club": {
10717
+ "data": {
10718
+ "id": "1",
10719
+ "type": "clubs"
10720
+ }
10721
+ }
10722
+ },
10723
+ "type": "players"
10724
+ }
10725
+ ]
10726
+ }
10727
+ ```
10728
+
10729
+ to the format that the Ember Data store expects.
10730
+
10731
+ @class JSONAPISerializer
10732
+ @namespace DS
10733
+ @extends DS.JSONSerializer
10734
+ */
10735
+ var ember$data$lib$serializers$json$api$serializer$$JSONAPISerializer = ember$data$lib$serializers$json$serializer$$default.extend({
10592
10736
 
10593
10737
  /**
10594
10738
  @method _normalizeDocumentHelper
@@ -10631,6 +10775,14 @@
10631
10775
  */
10632
10776
  _normalizeResourceHelper: function (resourceHash) {
10633
10777
  var modelName = this.modelNameFromPayloadKey(resourceHash.type);
10778
+
10779
+ if (!this.store._hasModelFor(modelName)) {
10780
+ Ember.warn(this.warnMessageNoModelForType(modelName, resourceHash.type), false, {
10781
+ id: 'ds.serializer.model-for-type-missing'
10782
+ });
10783
+ return null;
10784
+ }
10785
+
10634
10786
  var modelClass = this.store.modelFor(modelName);
10635
10787
  var serializer = this.store.serializerFor(modelName);
10636
10788
 
@@ -10942,6 +11094,16 @@
10942
11094
  }
10943
11095
  });
10944
11096
 
11097
+ Ember.runInDebug(function () {
11098
+ ember$data$lib$serializers$json$api$serializer$$JSONAPISerializer.reopen({
11099
+ warnMessageNoModelForType: function (modelName, originalType) {
11100
+ return 'Encountered a resource object with type "' + originalType + '", but no model was found for model name "' + modelName + '" (resolved model name using ' + this.constructor.toString() + '.modelNameFromPayloadKey("' + originalType + '"))';
11101
+ }
11102
+ });
11103
+ });
11104
+
11105
+ var ember$data$lib$serializers$json$api$serializer$$default = ember$data$lib$serializers$json$api$serializer$$JSONAPISerializer;
11106
+
10945
11107
  var ember$data$lib$serializers$rest$serializer$$camelize = Ember.String.camelize;
10946
11108
 
10947
11109
  /**