embient 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }