embient 0.0.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,38 +1,38 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- embient (0.0.9)
4
+ embient (0.1.0)
5
5
  emberjs-rails
6
6
  rails (>= 3.1.0)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- actionmailer (3.2.0)
12
- actionpack (= 3.2.0)
13
- mail (~> 2.4.0)
14
- actionpack (3.2.0)
15
- activemodel (= 3.2.0)
16
- activesupport (= 3.2.0)
11
+ actionmailer (3.2.3)
12
+ actionpack (= 3.2.3)
13
+ mail (~> 2.4.4)
14
+ actionpack (3.2.3)
15
+ activemodel (= 3.2.3)
16
+ activesupport (= 3.2.3)
17
17
  builder (~> 3.0.0)
18
18
  erubis (~> 2.7.0)
19
- journey (~> 1.0.0)
19
+ journey (~> 1.0.1)
20
20
  rack (~> 1.4.0)
21
- rack-cache (~> 1.1)
21
+ rack-cache (~> 1.2)
22
22
  rack-test (~> 0.6.1)
23
23
  sprockets (~> 2.1.2)
24
- activemodel (3.2.0)
25
- activesupport (= 3.2.0)
24
+ activemodel (3.2.3)
25
+ activesupport (= 3.2.3)
26
26
  builder (~> 3.0.0)
27
- activerecord (3.2.0)
28
- activemodel (= 3.2.0)
29
- activesupport (= 3.2.0)
30
- arel (~> 3.0.0)
27
+ activerecord (3.2.3)
28
+ activemodel (= 3.2.3)
29
+ activesupport (= 3.2.3)
30
+ arel (~> 3.0.2)
31
31
  tzinfo (~> 0.3.29)
32
- activeresource (3.2.0)
33
- activemodel (= 3.2.0)
34
- activesupport (= 3.2.0)
35
- activesupport (3.2.0)
32
+ activeresource (3.2.3)
33
+ activemodel (= 3.2.3)
34
+ activesupport (= 3.2.3)
35
+ activesupport (3.2.3)
36
36
  i18n (~> 0.6)
37
37
  multi_json (~> 1.0)
38
38
  arel (3.0.2)
@@ -41,7 +41,7 @@ GEM
41
41
  hamlbars
42
42
  rails (~> 3.1)
43
43
  erubis (2.7.0)
44
- execjs (1.3.0)
44
+ execjs (1.3.1)
45
45
  multi_json (~> 1.0)
46
46
  haml (3.1.4)
47
47
  hamlbars (2012.3.21)
@@ -52,13 +52,13 @@ GEM
52
52
  hike (1.2.1)
53
53
  i18n (0.6.0)
54
54
  journey (1.0.3)
55
- json (1.6.6)
55
+ json (1.7.0)
56
56
  mail (2.4.4)
57
57
  i18n (>= 0.4.0)
58
58
  mime-types (~> 1.16)
59
59
  treetop (~> 1.4.8)
60
60
  mime-types (1.18)
61
- multi_json (1.2.0)
61
+ multi_json (1.3.4)
62
62
  polyglot (0.3.3)
63
63
  rack (1.4.1)
64
64
  rack-cache (1.2)
@@ -67,17 +67,17 @@ GEM
67
67
  rack
68
68
  rack-test (0.6.1)
69
69
  rack (>= 1.0)
70
- rails (3.2.0)
71
- actionmailer (= 3.2.0)
72
- actionpack (= 3.2.0)
73
- activerecord (= 3.2.0)
74
- activeresource (= 3.2.0)
75
- activesupport (= 3.2.0)
70
+ rails (3.2.3)
71
+ actionmailer (= 3.2.3)
72
+ actionpack (= 3.2.3)
73
+ activerecord (= 3.2.3)
74
+ activeresource (= 3.2.3)
75
+ activesupport (= 3.2.3)
76
76
  bundler (~> 1.0)
77
- railties (= 3.2.0)
78
- railties (3.2.0)
79
- actionpack (= 3.2.0)
80
- activesupport (= 3.2.0)
77
+ railties (= 3.2.3)
78
+ railties (3.2.3)
79
+ actionpack (= 3.2.3)
80
+ activesupport (= 3.2.3)
81
81
  rack-ssl (~> 1.3.2)
82
82
  rake (>= 0.8.7)
83
83
  rdoc (~> 3.4)
@@ -85,7 +85,7 @@ GEM
85
85
  rake (0.9.2.2)
86
86
  rdoc (3.12)
87
87
  json (~> 1.4)
88
- sprockets (2.1.2)
88
+ sprockets (2.1.3)
89
89
  hike (~> 1.2)
90
90
  rack (~> 1.0)
91
91
  tilt (~> 1.1, != 1.3.0)
@@ -1,3 +1,3 @@
1
1
  module Embient
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -275,7 +275,7 @@ DS.ManyArray = DS.RecordArray.extend({
275
275
  var stateManager = get(this, 'stateManager');
276
276
 
277
277
  added = added.map(function(record) {
278
- ember_assert("You can only add records of " + (get(this, 'type') && get(this, 'type').toString()) + " to this association.", !get(this, 'type') || (get(this, 'type') === record.constructor));
278
+
279
279
 
280
280
  if (pendingParent) {
281
281
  record.send('waitingOn', parentRecord);
@@ -320,6 +320,21 @@ DS.ManyArray = DS.RecordArray.extend({
320
320
  if (actual) {
321
321
  set(record, actual.name, remove ? null : parentRecord);
322
322
  }
323
+ },
324
+
325
+ // Create a child record within the parentRecord
326
+ createRecord: function(hash, transaction) {
327
+ var parentRecord = get(this, 'parentRecord'),
328
+ store = get(parentRecord, 'store'),
329
+ type = get(this, 'type'),
330
+ record;
331
+
332
+ transaction = transaction || get(parentRecord, 'transaction');
333
+
334
+ record = store.createRecord.call(store, type, hash, transaction);
335
+ this.pushObject(record);
336
+
337
+ return record;
323
338
  }
324
339
  });
325
340
 
@@ -423,10 +438,11 @@ DS.Transaction = Ember.Object.extend({
423
438
  */
424
439
  init: function() {
425
440
  set(this, 'buckets', {
426
- clean: Ember.Map.create(),
427
- created: Ember.Map.create(),
428
- updated: Ember.Map.create(),
429
- deleted: Ember.Map.create()
441
+ clean: Ember.Map.create(),
442
+ created: Ember.Map.create(),
443
+ updated: Ember.Map.create(),
444
+ deleted: Ember.Map.create(),
445
+ inflight: Ember.Map.create()
430
446
  });
431
447
  },
432
448
 
@@ -455,12 +471,11 @@ DS.Transaction = Ember.Object.extend({
455
471
  */
456
472
  add: function(record) {
457
473
  // we could probably make this work if someone has a valid use case. Do you?
458
- ember_assert("Once a record has changed, you cannot move it into a different transaction", !get(record, 'isDirty'));
474
+
459
475
 
460
476
  var recordTransaction = get(record, 'transaction'),
461
477
  defaultTransaction = getPath(this, 'store.defaultTransaction');
462
478
 
463
- ember_assert("Models cannot belong to more than one transaction at a time.", recordTransaction === defaultTransaction);
464
479
 
465
480
  this.adoptRecord(record);
466
481
  },
@@ -518,7 +533,7 @@ DS.Transaction = Ember.Object.extend({
518
533
  this.removeCleanRecords();
519
534
 
520
535
  if (adapter && adapter.commit) { adapter.commit(store, commitDetails); }
521
- else { throw fmt("Adapter is either null or do not implement `commit` method", this); }
536
+ else { throw fmt("Adapter is either null or does not implement `commit` method", this); }
522
537
  },
523
538
 
524
539
  /**
@@ -542,7 +557,7 @@ DS.Transaction = Ember.Object.extend({
542
557
  // and initiate a rollback on them. As a side effect of telling
543
558
  // the record to roll back, it should also move itself out of
544
559
  // the dirty bucket and into the clean bucket.
545
- ['created', 'updated', 'deleted'].forEach(function(bucketType) {
560
+ ['created', 'updated', 'deleted', 'inflight'].forEach(function(bucketType) {
546
561
  dirty = this.bucketForType(bucketType);
547
562
 
548
563
  dirty.forEach(function(type, records) {
@@ -685,7 +700,21 @@ DS.Transaction = Ember.Object.extend({
685
700
  @private
686
701
 
687
702
  Called by a record's state manager to indicate that the record has entered
688
- a clean state. The record will be moved from its current dirty bucket and into
703
+ inflight state. The record will be moved from its current dirty bucket and into
704
+ the `inflight` bucket.
705
+
706
+ @param {String} bucketType one of `created`, `updated`, or `deleted`
707
+ */
708
+ recordBecameInFlight: function(kind, record) {
709
+ this.removeFromBucket(kind, record);
710
+ this.addToBucket('inflight', record);
711
+ },
712
+
713
+ /**
714
+ @private
715
+
716
+ Called by a record's state manager to indicate that the record has entered
717
+ a clean state. The record will be moved from its current dirty or inflight bucket and into
689
718
  the `clean` bucket.
690
719
 
691
720
  @param {String} bucketType one of `created`, `updated`, or `deleted`
@@ -693,8 +722,7 @@ DS.Transaction = Ember.Object.extend({
693
722
  recordBecameClean: function(kind, record) {
694
723
  this.removeFromBucket(kind, record);
695
724
 
696
- var defaultTransaction = getPath(this, 'store.defaultTransaction');
697
- defaultTransaction.adoptRecord(record);
725
+ this.remove(record);
698
726
  }
699
727
  });
700
728
 
@@ -870,7 +898,19 @@ DS.Store = Ember.Object.extend({
870
898
 
871
899
  // Extract the primary key from the `properties` hash,
872
900
  // based on the `primaryKey` for the model type.
873
- var id = properties[get(record, 'primaryKey')] || null;
901
+ var primaryKey = get(record, 'primaryKey'),
902
+ id = properties[primaryKey] || null;
903
+
904
+ // If the passed properties do not include a primary key,
905
+ // give the adapter an opportunity to generate one.
906
+ var adapter;
907
+ if (Ember.none(id)) {
908
+ adapter = get(this, 'adapter');
909
+ if (adapter && adapter.generateIdForRecord) {
910
+ id = adapter.generateIdForRecord(this, record);
911
+ properties.id = id;
912
+ }
913
+ }
874
914
 
875
915
  var hash = {}, clientId;
876
916
 
@@ -1196,6 +1236,8 @@ DS.Store = Ember.Object.extend({
1196
1236
  dataCache[clientId] = hash;
1197
1237
  record.send('didChangeData');
1198
1238
  record.hashWasUpdated();
1239
+ } else {
1240
+ record.send('didSaveData');
1199
1241
  }
1200
1242
 
1201
1243
  record.send('didCommit');
@@ -1221,7 +1263,7 @@ DS.Store = Ember.Object.extend({
1221
1263
  // of the data supercedes the local changes.
1222
1264
  record.beginPropertyChanges();
1223
1265
  record.send('didChangeData');
1224
- recordData.adapterDidUpdate(hash);
1266
+ recordData.adapterDidUpdate();
1225
1267
  record.hashWasUpdated();
1226
1268
  record.endPropertyChanges();
1227
1269
 
@@ -1260,11 +1302,11 @@ DS.Store = Ember.Object.extend({
1260
1302
 
1261
1303
  primaryKey = type.proto().primaryKey;
1262
1304
 
1263
- // TODO: Make ember_assert more flexible and convert this into an ember_assert
1305
+ // TODO: Make Ember.assert more flexible
1264
1306
  if (hash) {
1265
- ember_assert("The server must provide a primary key: " + primaryKey, get(hash, primaryKey));
1307
+
1266
1308
  } else {
1267
- ember_assert("The server did not return data, and you did not create a primary key (" + primaryKey + ") on the client", get(get(record, 'data'), primaryKey));
1309
+
1268
1310
  }
1269
1311
 
1270
1312
  clientId = get(record, 'clientId');
@@ -1437,7 +1479,7 @@ DS.Store = Ember.Object.extend({
1437
1479
  if (hash === undefined) {
1438
1480
  hash = id;
1439
1481
  var primaryKey = type.proto().primaryKey;
1440
- ember_assert("A data hash was loaded for a record of type " + type.toString() + " but no primary key '" + primaryKey + "' was provided.", primaryKey in hash);
1482
+
1441
1483
  id = hash[primaryKey];
1442
1484
  }
1443
1485
 
@@ -1579,7 +1621,7 @@ var get = Ember.get, set = Ember.set, getPath = Ember.getPath, guidFor = Ember.g
1579
1621
  string. You can determine a record's current state by getting its manager's
1580
1622
  current state path:
1581
1623
 
1582
- record.getPath('manager.currentState.path');
1624
+ record.getPath('stateManager.currentState.path');
1583
1625
  //=> "created.uncommitted"
1584
1626
 
1585
1627
  The `DS.Model` states are themselves stateless. What we mean is that,
@@ -1892,11 +1934,6 @@ var DirtyState = DS.State.extend({
1892
1934
  });
1893
1935
  },
1894
1936
 
1895
- exit: function(manager) {
1896
- var record = get(manager, 'record');
1897
- manager.send('invokeLifecycleCallbacks', record);
1898
- },
1899
-
1900
1937
  // EVENTS
1901
1938
  deleteRecord: Ember.K,
1902
1939
 
@@ -1909,6 +1946,17 @@ var DirtyState = DS.State.extend({
1909
1946
  manager.goToState('inFlight');
1910
1947
  },
1911
1948
 
1949
+ becameInvalid: function(manager) {
1950
+ var dirtyType = get(this, 'dirtyType'),
1951
+ record = get(manager, 'record');
1952
+
1953
+ record.withTransaction(function (t) {
1954
+ t.recordBecameInFlight(dirtyType, record);
1955
+ });
1956
+
1957
+ manager.goToState('invalid');
1958
+ },
1959
+
1912
1960
  rollback: function(manager) {
1913
1961
  var record = get(manager, 'record'),
1914
1962
  dirtyType = get(this, 'dirtyType'),
@@ -1937,20 +1985,35 @@ var DirtyState = DS.State.extend({
1937
1985
  record = get(manager, 'record');
1938
1986
 
1939
1987
  record.withTransaction(function (t) {
1940
- t.recordBecameClean(dirtyType, record);
1988
+ t.recordBecameInFlight(dirtyType, record);
1941
1989
  });
1942
1990
  },
1943
1991
 
1944
1992
  // EVENTS
1945
1993
  didCommit: function(manager) {
1994
+ var dirtyType = get(this, 'dirtyType'),
1995
+ record = get(manager, 'record');
1996
+
1997
+ record.withTransaction(function(t) {
1998
+ t.recordBecameClean('inflight', record);
1999
+ });
2000
+
1946
2001
  manager.goToState('loaded');
2002
+ manager.send('invokeLifecycleCallbacks', dirtyType);
1947
2003
  },
1948
2004
 
1949
2005
  becameInvalid: function(manager, errors) {
1950
2006
  var record = get(manager, 'record');
1951
2007
 
1952
2008
  set(record, 'errors', errors);
2009
+
1953
2010
  manager.goToState('invalid');
2011
+ manager.send('invokeLifecycleCallbacks');
2012
+ },
2013
+
2014
+ becameError: function(manager) {
2015
+ manager.goToState('error');
2016
+ manager.send('invokeLifecycleCallbacks');
1954
2017
  },
1955
2018
 
1956
2019
  didChangeData: didChangeData
@@ -2046,8 +2109,13 @@ var DirtyState = DS.State.extend({
2046
2109
  },
2047
2110
 
2048
2111
  willCommit: function(manager) {
2049
- var dirtyType = get(this, 'dirtyType');
2050
- manager.goToState(dirtyType + '.inFlight');
2112
+ var record = get(manager, 'record'),
2113
+ pendingQueue = get(record, 'pendingQueue');
2114
+
2115
+ if (isEmptyObject(pendingQueue)) {
2116
+ var dirtyType = get(this, 'dirtyType');
2117
+ manager.goToState(dirtyType + '.inFlight');
2118
+ }
2051
2119
  }
2052
2120
  })
2053
2121
  }),
@@ -2059,6 +2127,14 @@ var DirtyState = DS.State.extend({
2059
2127
  // FLAGS
2060
2128
  isValid: false,
2061
2129
 
2130
+ exit: function(manager) {
2131
+ var record = get(manager, 'record');
2132
+
2133
+ record.withTransaction(function (t) {
2134
+ t.recordBecameClean('inflight', record);
2135
+ });
2136
+ },
2137
+
2062
2138
  // EVENTS
2063
2139
  deleteRecord: function(manager) {
2064
2140
  manager.goToState('deleted');
@@ -2080,8 +2156,18 @@ var DirtyState = DS.State.extend({
2080
2156
  }
2081
2157
  },
2082
2158
 
2159
+ rollback: function(manager) {
2160
+ manager.send('becameValid');
2161
+ manager.send('rollback');
2162
+ },
2163
+
2083
2164
  becameValid: function(manager) {
2084
2165
  manager.goToState('uncommitted');
2166
+ },
2167
+
2168
+ invokeLifecycleCallbacks: function(manager) {
2169
+ var record = get(manager, 'record');
2170
+ record.fire('becameInvalid', record);
2085
2171
  }
2086
2172
  })
2087
2173
  });
@@ -2094,21 +2180,11 @@ var createdState = DirtyState.create({
2094
2180
  dirtyType: 'created',
2095
2181
 
2096
2182
  // FLAGS
2097
- isNew: true,
2098
-
2099
- // EVENTS
2100
- invokeLifecycleCallbacks: function(manager, record) {
2101
- record.fire('didCreate');
2102
- }
2183
+ isNew: true
2103
2184
  });
2104
2185
 
2105
2186
  var updatedState = DirtyState.create({
2106
- dirtyType: 'updated',
2107
-
2108
- // EVENTS
2109
- invokeLifecycleCallbacks: function(manager, record) {
2110
- record.fire('didUpdate');
2111
- }
2187
+ dirtyType: 'updated'
2112
2188
  });
2113
2189
 
2114
2190
  // The created.uncommitted state and created.pending.uncommitted share
@@ -2129,6 +2205,15 @@ createdState.states.uncommitted.reopen({
2129
2205
  // some logic defined in UpdatedUncommitted.
2130
2206
  updatedState.states.uncommitted.reopen(UpdatedUncommitted);
2131
2207
  updatedState.states.pending.states.uncommitted.reopen(UpdatedUncommitted);
2208
+ updatedState.states.inFlight.reopen({
2209
+ didSaveData: function(manager) {
2210
+ var record = get(manager, 'record'),
2211
+ data = get(record, 'data');
2212
+
2213
+ data.saveData();
2214
+ data.adapterDidUpdate();
2215
+ }
2216
+ });
2132
2217
 
2133
2218
  var states = {
2134
2219
  rootState: Ember.State.create({
@@ -2200,6 +2285,7 @@ var states = {
2200
2285
  // If there are no local changes to a record, it remains
2201
2286
  // in the `saved` state.
2202
2287
  saved: DS.State.create({
2288
+
2203
2289
  // EVENTS
2204
2290
  setProperty: function(manager, context) {
2205
2291
  setProperty(manager, context);
@@ -2220,6 +2306,15 @@ var states = {
2220
2306
  waitingOn: function(manager, object) {
2221
2307
  waitingOn(manager, object);
2222
2308
  manager.goToState('updated.pending');
2309
+ },
2310
+
2311
+ invokeLifecycleCallbacks: function(manager, dirtyType) {
2312
+ var record = get(manager, 'record');
2313
+ if (dirtyType === 'created') {
2314
+ record.fire('didCreate', record);
2315
+ } else {
2316
+ record.fire('didUpdate', record);
2317
+ }
2223
2318
  }
2224
2319
  }),
2225
2320
 
@@ -2290,17 +2385,25 @@ var states = {
2290
2385
  isSaving: true,
2291
2386
 
2292
2387
  // TRANSITIONS
2293
- exit: function(stateManager) {
2294
- var record = get(stateManager, 'record');
2388
+ enter: function(manager) {
2389
+ var record = get(manager, 'record');
2295
2390
 
2296
- record.withTransaction(function(t) {
2297
- t.recordBecameClean('deleted', record);
2391
+ record.withTransaction(function (t) {
2392
+ t.recordBecameInFlight('deleted', record);
2298
2393
  });
2299
2394
  },
2300
2395
 
2301
2396
  // EVENTS
2302
2397
  didCommit: function(manager) {
2398
+ var record = get(manager, 'record');
2399
+
2400
+ record.withTransaction(function(t) {
2401
+ t.recordBecameClean('inflight', record);
2402
+ });
2403
+
2303
2404
  manager.goToState('saved');
2405
+
2406
+ manager.send('invokeLifecycleCallbacks');
2304
2407
  }
2305
2408
  }),
2306
2409
 
@@ -2309,7 +2412,12 @@ var states = {
2309
2412
  // of `deleted`.
2310
2413
  saved: DS.State.create({
2311
2414
  // FLAGS
2312
- isDirty: false
2415
+ isDirty: false,
2416
+
2417
+ invokeLifecycleCallbacks: function(manager) {
2418
+ var record = get(manager, 'record');
2419
+ record.fire('didDelete', record);
2420
+ }
2313
2421
  })
2314
2422
  }),
2315
2423
 
@@ -2317,7 +2425,14 @@ var states = {
2317
2425
  // error saving a record, the record enters the `error`
2318
2426
  // state.
2319
2427
  error: DS.State.create({
2320
- isError: true
2428
+ isError: true,
2429
+
2430
+ // EVENTS
2431
+
2432
+ invokeLifecycleCallbacks: function(manager) {
2433
+ var record = get(manager, 'record');
2434
+ record.fire('becameError', record);
2435
+ }
2321
2436
  })
2322
2437
  })
2323
2438
  };
@@ -2402,6 +2517,18 @@ DataProxy.prototype = {
2402
2517
  },
2403
2518
 
2404
2519
  commit: function() {
2520
+ this.saveData();
2521
+
2522
+ this.record.notifyPropertyChange('data');
2523
+ },
2524
+
2525
+ rollback: function() {
2526
+ this.unsavedData = {};
2527
+
2528
+ this.record.notifyPropertyChange('data');
2529
+ },
2530
+
2531
+ saveData: function() {
2405
2532
  var record = this.record;
2406
2533
 
2407
2534
  var unsavedData = this.unsavedData;
@@ -2413,17 +2540,9 @@ DataProxy.prototype = {
2413
2540
  delete unsavedData[prop];
2414
2541
  }
2415
2542
  }
2416
-
2417
- record.notifyPropertyChange('data');
2418
- },
2419
-
2420
- rollback: function() {
2421
- this.unsavedData = {};
2422
-
2423
- this.record.notifyPropertyChange('data');
2424
2543
  },
2425
2544
 
2426
- adapterDidUpdate: function(data) {
2545
+ adapterDidUpdate: function() {
2427
2546
  this.unsavedData = {};
2428
2547
  }
2429
2548
  };
@@ -2535,7 +2654,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2535
2654
  addHasManyToJSON: function(json, data, meta, options) {
2536
2655
  var key = meta.key,
2537
2656
  manyArray = get(this, key),
2538
- records = [],
2657
+ records = [], i, l,
2539
2658
  clientId, id;
2540
2659
 
2541
2660
  if (meta.options.embedded) {
@@ -2546,7 +2665,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2546
2665
  } else {
2547
2666
  var clientIds = get(manyArray, 'content');
2548
2667
 
2549
- for (var i=0, l=clientIds.length; i<l; i++) {
2668
+ for (i=0, l=clientIds.length; i<l; i++) {
2550
2669
  clientId = clientIds[i];
2551
2670
  id = get(this, 'store').clientIdToId[clientId];
2552
2671
 
@@ -2556,7 +2675,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2556
2675
  }
2557
2676
  }
2558
2677
 
2559
- key = options.key || get(this, 'namingConvention').keyToJSONKey(key);
2678
+ key = meta.options.key || get(this, 'namingConvention').keyToJSONKey(key);
2560
2679
  json[key] = records;
2561
2680
  },
2562
2681
 
@@ -2573,12 +2692,12 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2573
2692
  addBelongsToToJSON: function(json, data, meta, options) {
2574
2693
  var key = meta.key, value, id;
2575
2694
 
2576
- if (options.embedded) {
2577
- key = options.key || get(this, 'namingConvention').keyToJSONKey(key);
2695
+ if (meta.options.embedded) {
2696
+ key = meta.options.key || get(this, 'namingConvention').keyToJSONKey(key);
2578
2697
  value = get(data.record, key);
2579
2698
  json[key] = value ? value.toJSON(options) : null;
2580
2699
  } else {
2581
- key = options.key || get(this, 'namingConvention').foreignKey(key);
2700
+ key = meta.options.key || get(this, 'namingConvention').foreignKey(key);
2582
2701
  id = data.get(key);
2583
2702
  json[key] = none(id) ? null : id;
2584
2703
  }
@@ -2628,6 +2747,9 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2628
2747
  didLoad: Ember.K,
2629
2748
  didUpdate: Ember.K,
2630
2749
  didCreate: Ember.K,
2750
+ didDelete: Ember.K,
2751
+ becameInvalid: Ember.K,
2752
+ becameError: Ember.K,
2631
2753
 
2632
2754
  init: function() {
2633
2755
  var stateManager = DS.StateManager.create({
@@ -2679,7 +2801,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2679
2801
  var data = get(this, 'data');
2680
2802
 
2681
2803
  if (data && key in data) {
2682
- ember_assert("You attempted to access the " + key + " property on a record without defining an attribute.", false);
2804
+
2683
2805
  }
2684
2806
  },
2685
2807
 
@@ -2687,7 +2809,7 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2687
2809
  var data = get(this, 'data');
2688
2810
 
2689
2811
  if (data && key in data) {
2690
- ember_assert("You attempted to set the " + key + " property on a record without defining an attribute.", false);
2812
+
2691
2813
  } else {
2692
2814
  return this._super(key, value);
2693
2815
  }
@@ -2723,7 +2845,8 @@ DS.Model = Ember.Object.extend(Ember.Evented, {
2723
2845
  cachedValue = this.cacheFor(name);
2724
2846
 
2725
2847
  if (cachedValue) {
2726
- var ids = data.get(name) || [];
2848
+ var key = association.options.key || name,
2849
+ ids = data.get(key) || [];
2727
2850
  var clientIds = Ember.ArrayUtils.map(ids, function(id) {
2728
2851
  return store.clientIdForId(association.type, id);
2729
2852
  });
@@ -2806,7 +2929,7 @@ DS.Model.reopenClass({
2806
2929
 
2807
2930
  DS.attr = function(type, options) {
2808
2931
  var transform = DS.attr.transforms[type];
2809
- ember_assert("Could not find model attribute of type " + type, !!transform);
2932
+
2810
2933
 
2811
2934
  var transformFrom = transform.from;
2812
2935
  var transformTo = transform.to;
@@ -2995,7 +3118,7 @@ var hasAssociation = function(type, options, one) {
2995
3118
  };
2996
3119
 
2997
3120
  DS.belongsTo = function(type, options) {
2998
- ember_assert("The type passed to DS.belongsTo must be defined", !!type);
3121
+
2999
3122
  return hasAssociation(type, options);
3000
3123
  };
3001
3124
 
@@ -3031,7 +3154,7 @@ var hasAssociation = function(type, options) {
3031
3154
  type = getPath(this, type, false) || getPath(window, type);
3032
3155
  }
3033
3156
 
3034
- key = options.key || key;
3157
+ key = options.key || get(this, 'namingConvention').keyToJSONKey(key);
3035
3158
  ids = findRecord(store, type, data, key);
3036
3159
  association = store.findMany(type, ids);
3037
3160
  set(association, 'parentRecord', this);
@@ -3041,7 +3164,7 @@ var hasAssociation = function(type, options) {
3041
3164
  };
3042
3165
 
3043
3166
  DS.hasMany = function(type, options) {
3044
- ember_assert("The type passed to DS.hasMany must be defined", !!type);
3167
+
3045
3168
  return hasAssociation(type, options);
3046
3169
  };
3047
3170
 
@@ -3115,7 +3238,93 @@ DS.Model.reopenClass({
3115
3238
 
3116
3239
 
3117
3240
  (function() {
3241
+ /**
3242
+ An adapter is an object that receives requests from a store and
3243
+ translates them into the appropriate action to take against your
3244
+ persistence layer. The persistence layer is usually an HTTP API, but may
3245
+ be anything, such as the browser's local storage.
3246
+
3247
+ ### Creating an Adapter
3248
+
3249
+ First, create a new subclass of `DS.Adapter`:
3250
+
3251
+ App.MyAdapter = DS.Adapter.extend({
3252
+ // ...your code here
3253
+ });
3254
+
3255
+ To tell your store which adapter to use, set its `adapter` property:
3256
+
3257
+ App.store = DS.Store.create({
3258
+ revision: 3,
3259
+ adapter: App.MyAdapter.create()
3260
+ });
3261
+
3262
+ `DS.Adapter` is an abstract base class that you should override in your
3263
+ application to customize it for your backend. The minimum set of methods
3264
+ that you should implement is:
3265
+
3266
+ * `find()`
3267
+ * `createRecord()`
3268
+ * `updateRecord()`
3269
+ * `deleteRecord()`
3270
+
3271
+ To improve the network performance of your application, you can optimize
3272
+ your adapter by overriding these lower-level methods:
3273
+
3274
+ * `findMany()`
3275
+ * `createRecords()`
3276
+ * `updateRecords()`
3277
+ * `deleteRecords()`
3278
+ * `commit()`
3279
+
3280
+ For more information about the adapter API, please see `README.md`.
3281
+ */
3282
+
3118
3283
  DS.Adapter = Ember.Object.extend({
3284
+ /**
3285
+ The `find()` method is invoked when the store is asked for a record that
3286
+ has not previously been loaded. In response to `find()` being called, you
3287
+ should query your persistence layer for a record with the given ID. Once
3288
+ found, you can asynchronously call the store's `load()` method to load
3289
+ the record.
3290
+
3291
+ Here is an example `find` implementation:
3292
+
3293
+ find: function(store, type, id) {
3294
+ var url = type.url;
3295
+ url = url.fmt(id);
3296
+
3297
+ jQuery.getJSON(url, function(data) {
3298
+ // data is a Hash of key/value pairs. If your server returns a
3299
+ // root, simply do something like:
3300
+ // store.load(type, id, data.person)
3301
+ store.load(type, id, data);
3302
+ });
3303
+ }
3304
+ */
3305
+ find: null,
3306
+
3307
+ /**
3308
+ If the globally unique IDs for your records should be generated on the client,
3309
+ implement the `generateIdForRecord()` method. This method will be invoked
3310
+ each time you create a new record, and the value returned from it will be
3311
+ assigned to the record's `primaryKey`.
3312
+
3313
+ Most traditional REST-like HTTP APIs will not use this method. Instead, the ID
3314
+ of the record will be set by the server, and your adapter will update the store
3315
+ with the new ID when it calls `didCreateRecord()`. Only implement this method if
3316
+ you intend to generate record IDs on the client-side.
3317
+
3318
+ The `generateIdForRecord()` method will be invoked with the requesting store as
3319
+ the first parameter and the newly created record as the second parameter:
3320
+
3321
+ generateIdForRecord: function(store, record) {
3322
+ var uuid = App.generateUUIDWithStatisticallyLowOddsOfCollision();
3323
+ return uuid;
3324
+ }
3325
+ */
3326
+ generateIdForRecord: null,
3327
+
3119
3328
  commit: function(store, commitDetails) {
3120
3329
  commitDetails.updated.eachType(function(type, array) {
3121
3330
  this.updateRecords(store, type, array.slice());
@@ -3164,7 +3373,6 @@ DS.fixtureAdapter = DS.Adapter.create({
3164
3373
  find: function(store, type, id) {
3165
3374
  var fixtures = type.FIXTURES;
3166
3375
 
3167
- ember_assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
3168
3376
  if (fixtures.hasLoaded) { return; }
3169
3377
 
3170
3378
  setTimeout(function() {
@@ -3180,7 +3388,6 @@ DS.fixtureAdapter = DS.Adapter.create({
3180
3388
  findAll: function(store, type) {
3181
3389
  var fixtures = type.FIXTURES;
3182
3390
 
3183
- ember_assert("Unable to find fixtures for model type "+type.toString(), !!fixtures);
3184
3391
 
3185
3392
  var ids = fixtures.map(function(item, index, self){ return item.id; });
3186
3393
  store.loadMany(type, ids, fixtures);
@@ -3198,6 +3405,8 @@ DS.fixtureAdapter = DS.Adapter.create({
3198
3405
  var get = Ember.get, set = Ember.set, getPath = Ember.getPath;
3199
3406
 
3200
3407
  DS.RESTAdapter = DS.Adapter.extend({
3408
+ bulkCommit: false,
3409
+
3201
3410
  createRecord: function(store, type, record) {
3202
3411
  var root = this.rootForType(type);
3203
3412
 
@@ -3325,7 +3534,7 @@ DS.RESTAdapter = DS.Adapter.extend({
3325
3534
  this.ajax(this.buildURL(root), "GET", {
3326
3535
  data: { ids: ids },
3327
3536
  success: function(json) {
3328
- store.loadMany(type, ids, json[plural]);
3537
+ store.loadMany(type, json[plural]);
3329
3538
  this.sideload(store, type, json, plural);
3330
3539
  }
3331
3540
  });
@@ -3377,7 +3586,7 @@ DS.RESTAdapter = DS.Adapter.extend({
3377
3586
  hash.url = url;
3378
3587
  hash.type = type;
3379
3588
  hash.dataType = 'json';
3380
- hash.contentType = 'application/json';
3589
+ hash.contentType = 'application/json; charset=utf-8';
3381
3590
  hash.context = this;
3382
3591
 
3383
3592
  if (hash.data && type !== 'GET') {
@@ -3399,11 +3608,9 @@ DS.RESTAdapter = DS.Adapter.extend({
3399
3608
  if (!sideloadedType) {
3400
3609
  mappings = get(this, 'mappings');
3401
3610
 
3402
- ember_assert("Your server returned a hash with the key " + prop + " but you have no mappings", !!mappings);
3403
3611
 
3404
- sideloadedType = get(get(this, 'mappings'), prop);
3612
+ sideloadedType = get(mappings, prop);
3405
3613
 
3406
- ember_assert("Your server returned a hash with the key " + prop + " but you have no mapping for it", !!sideloadedType);
3407
3614
  }
3408
3615
 
3409
3616
  this.loadValue(store, sideloadedType, json[prop]);
@@ -3421,6 +3628,9 @@ DS.RESTAdapter = DS.Adapter.extend({
3421
3628
  buildURL: function(record, suffix) {
3422
3629
  var url = [""];
3423
3630
 
3631
+
3632
+
3633
+
3424
3634
  if (this.namespace !== undefined) {
3425
3635
  url.push(this.namespace);
3426
3636
  }