sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/Buildfile +4 -3
  2. data/VERSION.yml +2 -2
  3. data/buildtasks/entry.rake +3 -0
  4. data/buildtasks/manifest.rake +35 -9
  5. data/buildtasks/target.rake +25 -6
  6. data/frameworks/sproutcore/Buildfile +10 -0
  7. data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +41 -20
  8. data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +14 -43
  9. data/frameworks/sproutcore/frameworks/datastore/models/record.js +11 -0
  10. data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +6 -3
  11. data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +5 -1
  12. data/frameworks/sproutcore/frameworks/datastore/system/query.js +10 -7
  13. data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +19 -20
  14. data/frameworks/sproutcore/frameworks/datastore/system/store.js +126 -93
  15. data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +9 -3
  16. data/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -1
  17. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +28 -3
  18. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +13 -5
  19. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +46 -23
  20. data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +29 -5
  21. data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +13 -4
  22. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +109 -0
  23. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +69 -15
  24. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +20 -1
  25. data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +4 -1
  26. data/frameworks/sproutcore/frameworks/datastore/tests/system/query/find_all.js +56 -6
  27. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +9 -2
  28. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +45 -2
  29. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +0 -1
  30. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +53 -6
  31. data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +0 -5
  32. data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +47 -27
  33. data/frameworks/sproutcore/frameworks/desktop/system/drag.js +5 -4
  34. data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +23 -12
  35. data/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +92 -0
  36. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +104 -53
  37. data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +2 -0
  38. data/frameworks/sproutcore/frameworks/desktop/views/button.js +4 -3
  39. data/frameworks/sproutcore/frameworks/desktop/views/collection.js +6 -2
  40. data/frameworks/sproutcore/frameworks/desktop/views/list.js +9 -0
  41. data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
  42. data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +3 -3
  43. data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +9 -1
  44. data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +80 -102
  45. data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +0 -1
  46. data/frameworks/sproutcore/frameworks/foundation/english.lproj/text_field.css +5 -1
  47. data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +8 -1
  48. data/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +0 -1
  49. data/frameworks/sproutcore/frameworks/foundation/system/datetime.js +31 -3
  50. data/frameworks/sproutcore/frameworks/foundation/system/event.js +0 -4
  51. data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +3 -7
  52. data/frameworks/sproutcore/frameworks/foundation/system/request.js +3 -4
  53. data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +78 -17
  54. data/frameworks/sproutcore/frameworks/foundation/system/utils.js +9 -0
  55. data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/single_case.js +2 -2
  56. data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +2 -2
  57. data/frameworks/sproutcore/frameworks/foundation/tests/system/datetime.js +5 -0
  58. data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +2 -2
  59. data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +1 -4
  60. data/frameworks/sproutcore/frameworks/foundation/tests/validators/validator.js +20 -0
  61. data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +13 -0
  62. data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +132 -0
  63. data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +6 -3
  64. data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +8 -5
  65. data/frameworks/sproutcore/frameworks/foundation/views/image.js +18 -5
  66. data/frameworks/sproutcore/frameworks/foundation/views/text_field.js +292 -21
  67. data/frameworks/sproutcore/frameworks/foundation/views/view.js +13 -14
  68. data/frameworks/sproutcore/frameworks/mini/license.js +28 -0
  69. data/frameworks/sproutcore/frameworks/runtime/core.js +35 -0
  70. data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
  71. data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +79 -5
  72. data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +6 -6
  73. data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +53 -0
  74. data/frameworks/sproutcore/frameworks/testing/system/plan.js +4 -0
  75. data/frameworks/sproutcore/frameworks/testing/system/runner.js +1 -1
  76. data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +4 -0
  77. data/gen/design/Buildfile +23 -0
  78. data/gen/design/README +1 -0
  79. data/gen/design/USAGE +10 -0
  80. data/gen/design/templates/english.lproj/@filename@.js +16 -0
  81. data/gen/page/Buildfile +36 -0
  82. data/gen/page/README +1 -0
  83. data/gen/page/USAGE +15 -0
  84. data/gen/page/templates/pages/@target_name@/Buildfile +16 -0
  85. data/gen/page/templates/pages/@target_name@/core.js +22 -0
  86. data/gen/page/templates/pages/@target_name@/english.lproj/body.css +1 -0
  87. data/gen/page/templates/pages/@target_name@/english.lproj/body.rhtml +7 -0
  88. data/gen/page/templates/pages/@target_name@/english.lproj/strings.js +15 -0
  89. data/gen/view/README +1 -1
  90. data/gen/view/USAGE +5 -5
  91. data/lib/sproutcore/builders/base.rb +13 -2
  92. data/lib/sproutcore/builders/html.rb +28 -1
  93. data/lib/sproutcore/builders/minify.rb +84 -18
  94. data/lib/sproutcore/builders/test.rb +2 -1
  95. data/lib/sproutcore/helpers/entry_sorter.rb +16 -1
  96. data/lib/sproutcore/helpers/static_helper.rb +32 -4
  97. data/lib/sproutcore/helpers/tag_helper.rb +65 -0
  98. data/lib/sproutcore/models/manifest.rb +40 -6
  99. data/lib/sproutcore/models/target.rb +12 -3
  100. data/lib/sproutcore/rack/builder.rb +56 -4
  101. data/lib/sproutcore/tools/manifest.rb +1 -0
  102. data/lib/sproutcore/tools/server.rb +1 -0
  103. data/lib/sproutcore/tools.rb +21 -1
  104. data/lib/sproutcore.rb +13 -0
  105. metadata +16 -1
@@ -197,20 +197,6 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
197
197
  */
198
198
  revisions: null,
199
199
 
200
- /** @private
201
- Stores three sets of record property changes (storeKeys, statuses
202
- and recordTypes) which is used when _notifyRecordPropertyChange is
203
- called. Makes it possible to only execute once at the end of
204
- the runloop.
205
-
206
- @property {Hash}
207
- */
208
- recordPropertyChanges: {
209
- storeKeys: [],
210
- records: [],
211
- statusOnly: []
212
- },
213
-
214
200
  /**
215
201
  Array indicates whether a data hash is possibly in use by an external
216
202
  record for editing. If a data hash is editable then it may be modified
@@ -366,7 +352,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
366
352
  hash. If no status is found, returns SC.RECORD_EMPTY.
367
353
 
368
354
  @param {Number} storeKey the store key
369
- @returns {String} status
355
+ @returns {Number} status
370
356
  */
371
357
  readStatus: function(storeKey) {
372
358
  // use readDataHash to handle optimistic locking. this could be inlined
@@ -375,6 +361,18 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
375
361
  return this.statuses[storeKey] || SC.Record.EMPTY;
376
362
  },
377
363
 
364
+ /**
365
+ Reads the current status for the storeKey without actually locking the
366
+ record. Usually you won't need to use this method. It is mostly used
367
+ internally.
368
+
369
+ @param {Number} storeKey the store key
370
+ @returns {Number} status
371
+ */
372
+ peekStatus: function(storeKey) {
373
+ return this.statuses[storeKey] || SC.Record.EMPTY;
374
+ },
375
+
378
376
  /**
379
377
  Writes the current status for a storeKey.
380
378
 
@@ -415,15 +413,12 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
415
413
  storeKey = storeKeys;
416
414
  }
417
415
 
418
- SC.RunLoop.begin();
419
416
  for(idx=0;idx<len;idx++) {
420
417
  if (isArray) storeKey = storeKeys[idx];
421
418
  this.revisions[storeKey] = rev;
422
419
  this._notifyRecordPropertyChange(storeKey, statusOnly);
423
420
  }
424
421
 
425
- SC.RunLoop.end();
426
-
427
422
  return this ;
428
423
  },
429
424
 
@@ -433,58 +428,66 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
433
428
  */
434
429
  _notifyRecordPropertyChange: function(storeKey, statusOnly) {
435
430
 
436
- var records = this.records, rec, editState;
431
+ var records = this.records,
432
+ nestedStores = this.get('nestedStores'),
433
+ K = SC.Store,
434
+ rec, editState, len, idx, store, status;
437
435
 
438
436
  // pass along to nested stores
439
- var nestedStores = this.get('nestedStores'), len, idx, store, status;
440
- var K = SC.Store;
441
437
  len = nestedStores ? nestedStores.length : 0 ;
442
438
  for(idx=0;idx<len;idx++) {
443
439
  store = nestedStores[idx];
444
- status = store.readStatus(storeKey);
440
+ status = store.peekStatus(storeKey); // important: peek avoids read-lock
445
441
  editState = store.storeKeyEditState(storeKey);
446
442
 
447
443
  // when store needs to propagate out changes in the parent store
448
444
  // to nested stores
449
- if(editState!==K.INHERITED && (status & SC.Record.BUSY)) {
445
+ if (editState === K.INHERITED) {
446
+ store._notifyRecordPropertyChange(storeKey, statusOnly);
447
+
448
+ } else if (status & SC.Record.BUSY) {
450
449
  // make sure nested store does not have any changes before resetting
451
450
  if(store.get('hasChanges')) throw K.CHAIN_CONFLICT_ERROR;
452
451
  store.reset();
453
452
  }
454
-
455
- if(store.storeKeyEditState(storeKey) === K.INHERITED) {
456
- store._notifyRecordPropertyChange(storeKey, statusOnly);
457
- }
458
453
  }
459
454
 
460
455
  // schedule
461
- this.recordPropertyChanges.storeKeys.push(storeKey);
456
+ var changes = this.recordPropertyChanges;
457
+ if (!changes) {
458
+ changes = this.recordPropertyChanges =
459
+ { storeKeys: [], records: [], statusOnly: [] };
460
+ }
462
461
 
462
+ changes.storeKeys.push(storeKey);
463
+
463
464
  if (records && (rec=records[storeKey])) {
464
- this.recordPropertyChanges.records.push(storeKey);
465
- if(statusOnly) {
466
- this.recordPropertyChanges.statusOnly.push(storeKey);
467
- }
465
+ changes.records.push(storeKey);
466
+ if(statusOnly) changes.statusOnly.push(storeKey);
468
467
  }
469
-
470
- this._flushRecordChanges();
471
-
468
+
469
+ this.invokeOnce(this.flush);
472
470
  return this;
473
471
  },
474
-
475
- /** @private
476
- Will notify any record instances of the property change at the end of
477
- the run loop. Also notifies any inherited record instances as well.
478
-
479
- Will also notify any record arrays with queries to refresh based on
480
- the new/changed store keys.
472
+
473
+ /**
474
+ Delivers any pending changes to materialized records. Normally this
475
+ happens once, automatically, at the end of the RunLoop. If you have
476
+ updated some records and need to update records immediately, however,
477
+ you may call this manually.
478
+
479
+ @returns {SC.Store} receiver
481
480
  */
482
-
483
- _flushRecordChanges: function() {
484
- var storeKeys = this.recordPropertyChanges.storeKeys,
485
- statusOnly = this.recordPropertyChanges.statusOnly,
486
- records = this.recordPropertyChanges.records, rec,
487
- recordType, recordTypes = SC.Set.create(), status, idx, len, storeKey;
481
+ flush: function() {
482
+
483
+ if (!this.recordPropertyChanges) return this;
484
+
485
+ var changes = this.recordPropertyChanges,
486
+ storeKeys = changes.storeKeys,
487
+ statusOnly = changes.statusOnly,
488
+ records = changes.records,
489
+ recordTypes = SC.Set.create(),
490
+ rec, recordType, status, idx, len, storeKey;
488
491
 
489
492
  for(idx=0,len=storeKeys.length;idx<len;idx++) {
490
493
  storeKey = storeKeys[idx];
@@ -492,7 +495,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
492
495
  if(records.indexOf(storeKey)!==-1) {
493
496
  status = statusOnly.indexOf(storeKey)!==-1 ? YES: NO;
494
497
  rec = this.records[storeKey];
495
- rec.storeDidChangeProperties(status);
498
+ if(rec) rec.storeDidChangeProperties(status);
496
499
  // remove it so we don't trigger this twice
497
500
  records.removeObject(storeKey);
498
501
  }
@@ -503,18 +506,14 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
503
506
  }
504
507
 
505
508
  }
506
-
507
509
  this._notifyRecordArraysWithQuery(storeKeys, recordTypes);
508
-
509
- // reset for next run loop
510
- this.recordPropertyChanges.storeKeys = [];
511
- this.recordPropertyChanges.records = [];
512
- this.recordPropertyChanges.statusOnly = [];
510
+ this.recordPropertyChanges = null;
511
+ return this;
513
512
  },
514
513
 
515
514
  /** @private
516
515
  Will ask all record arrays that have been returned from findAll
517
- with an SC.Query to reapply their query with the new storeKeys
516
+ with an SC.Query to check their arrays with the new storeKeys
518
517
 
519
518
  @param {SC.IndexSet} storeKeys set of storeKeys that changed
520
519
  @param {SC.Set} recordTypes
@@ -526,8 +525,8 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
526
525
 
527
526
  for(var idx=0, len=recordArrays.length;idx<len;idx++) {
528
527
  var recArray = recordArrays[idx];
529
- // if this record array still exists, reapply the query
530
- if(recArray) recArray.applyQuery(storeKeys, recordTypes, YES);
528
+ // if this record array still exists, check storeKeys
529
+ if(recArray) recArray.applyQuery(storeKeys, recordTypes);
531
530
  }
532
531
  },
533
532
 
@@ -551,12 +550,10 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
551
550
 
552
551
  var records = this.records, storeKey;
553
552
  if (records) {
554
- SC.RunLoop.begin();
555
553
  for(storeKey in records) {
556
554
  if (!records.hasOwnProperty(storeKey)) continue ;
557
555
  this._notifyRecordPropertyChange(storeKey, NO);
558
556
  }
559
- SC.RunLoop.end();
560
557
  }
561
558
 
562
559
  this.set('hasChanges', NO);
@@ -598,8 +595,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
598
595
  chDataHashes = nestedStore.dataHashes;
599
596
  chRevisions = nestedStore.revisions ;
600
597
  chStatuses = nestedStore.statuses;
601
-
602
- SC.RunLoop.begin();
598
+
603
599
  for(i=0;i<len;i++) {
604
600
  storeKey = changes[i];
605
601
 
@@ -612,7 +608,6 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
612
608
 
613
609
  this._notifyRecordPropertyChange(storeKey, NO);
614
610
  }
615
- SC.RunLoop.end();
616
611
 
617
612
  // add any records to the changelog for commit handling
618
613
  var myChangelog = this.changelog, chChangelog = nestedStore.changelog;
@@ -622,6 +617,10 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
622
617
  }
623
618
  this.changelog = myChangelog;
624
619
 
620
+ // immediately flush changes to notify records - nested stores will flush
621
+ // later on.
622
+ if (!this.get('parentStore')) this.flush();
623
+
625
624
  return this ;
626
625
  },
627
626
 
@@ -674,10 +673,12 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
674
673
 
675
674
  @param {SC.Record|String} recordType the expected record type
676
675
  @param {String} id the id to load
676
+ @param {Hash} params optional additional parameters to pass along to the
677
+ data source
677
678
  @param {Boolean} isRefresh
678
679
  @returns {SC.Record} record instance or null
679
680
  */
680
- find: function(recordType, id, isRefresh) {
681
+ find: function(recordType, id, params, isRefresh) {
681
682
  // if recordType is passed as string, find object
682
683
  if(SC.typeOf(recordType)===SC.T_STRING) {
683
684
  recordType = SC.objectForPropertyPath(recordType);
@@ -752,7 +753,8 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
752
753
  else if (source) {
753
754
  // call fetch() on the data source.
754
755
  sourceRet = source.fetch.call(source, this, fetchKey, params);
755
- if(SC.typeOf(sourceRet)===SC.T_ARRAY) {
756
+ var typeRet = SC.typeOf(sourceRet);
757
+ if(typeRet===SC.T_ARRAY || (typeRet===SC.T_OBJECT && sourceRet.isSCArray)) {
756
758
  storeKeys = sourceRet;
757
759
  }
758
760
  }
@@ -1169,7 +1171,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1169
1171
  ret = [],
1170
1172
  rev = SC.Store.generateStoreKey(),
1171
1173
  K = SC.Record,
1172
- recordType, idx, storeKey, status;
1174
+ recordType, idx, storeKey, status, ok;
1173
1175
 
1174
1176
  if (!isArray) recordType = recordTypes;
1175
1177
 
@@ -1214,10 +1216,30 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1214
1216
  }
1215
1217
  }
1216
1218
 
1217
- // now retrieve storekeys from dataSource
1218
- if (source) {
1219
- var ok = source.retrieveRecords.call(source, this, ret, ids);
1220
- if (ok === NO) ret.length = 0; // could not find.
1219
+ // now retrieve storekeys from dataSource. if there is no dataSource,
1220
+ // then act as if we couldn't retrieve.
1221
+ ok = NO;
1222
+ if (source) ok = source.retrieveRecords.call(source, this, ret, ids);
1223
+
1224
+ // if the data source could not retrieve or if there is no source, then
1225
+ // simulate the data source calling dataSourceDidError on those we are
1226
+ // loading for the first time or dataSourceDidComplete on refreshes.
1227
+ if (!ok) {
1228
+ len = ret.length;
1229
+ rev = SC.Store.generateStoreKey();
1230
+ for(idx=0;idx<len;idx++) {
1231
+ storeKey = ret[idx];
1232
+ status = this.readStatus(storeKey);
1233
+ if (status === K.BUSY_LOADING) {
1234
+ this.writeStatus(storeKey, K.ERROR);
1235
+ this.dataHashDidChange(storeKey, rev, YES);
1236
+
1237
+ } else if (status & K.BUSY_REFRESH) {
1238
+ this.writeStatus(storeKey, K.READY | (status & 0x03));
1239
+ this.dataHashDidChange(storeKey, rev, YES);
1240
+ }
1241
+ }
1242
+ ret.length = 0 ; // truncate to indicate that none could refresh
1221
1243
  }
1222
1244
  return ret ;
1223
1245
  },
@@ -1270,7 +1292,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1270
1292
  @returns {Boolean} YES if the retrieval was a success.
1271
1293
  */
1272
1294
  refreshRecord: function(recordType, id, storeKey) {
1273
- return this.retrieveRecord(recordType, id, storeKey, YES);
1295
+ return !!this.retrieveRecord(recordType, id, storeKey, YES);
1274
1296
  },
1275
1297
 
1276
1298
  /**
@@ -1284,20 +1306,27 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1284
1306
  @returns {Boolean} YES if the retrieval was a success.
1285
1307
  */
1286
1308
  refreshRecords: function(recordTypes, ids, storeKeys) {
1287
- return this.retrieveRecords(recordTypes, ids, storeKeys, YES);
1309
+ var ret = this.retrieveRecords(recordTypes, ids, storeKeys, YES);
1310
+ return ret && ret.length>0;
1288
1311
  },
1289
1312
 
1290
1313
  /**
1291
- Commits the passed store keys. Based on the current state of the
1292
- record, this will ask the data source to perform the appropriate actions
1314
+ Commits the passed store keys or ids. If no storeKeys are given
1315
+ it will commit any records in the changelog.
1316
+
1317
+ Based on the current state of the record, this will ask the data
1318
+ source to perform the appropriate actions
1293
1319
  on the store keys.
1294
1320
 
1295
- @param {String} id to id of the record to load
1296
- @param {SC.Record} recordType the expected record type
1321
+ @param {Array} recordTypes the expected record types (SC.Record)
1322
+ @param {Array} ids to commit
1323
+ @param {Array} storeKeys to commit
1324
+ @param {Hash} params optional additional parameters to pass along to the
1325
+ data source
1297
1326
 
1298
1327
  @returns {SC.Bool} if the action was succesful.
1299
1328
  */
1300
- commitRecords: function(recordTypes, ids, storeKeys) {
1329
+ commitRecords: function(recordTypes, ids, storeKeys, params) {
1301
1330
  var source = this._getDataSource(),
1302
1331
  isArray = SC.typeOf(recordTypes) === SC.T_ARRAY,
1303
1332
  retCreate= [], retUpdate= [], retDestroy = [],
@@ -1308,14 +1337,14 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1308
1337
  // If no params are passed, look up storeKeys in the changelog property.
1309
1338
  // Remove any committed records from changelog property.
1310
1339
 
1311
- if(recordTypes===undefined && ids===undefined && storeKeys===undefined){
1312
- storeKeys=this.changelog;
1340
+ if(!recordTypes && !ids && !storeKeys){
1341
+ storeKeys = this.changelog;
1313
1342
  }
1314
1343
 
1315
1344
  // if no storeKeys or ids at this point, return
1316
1345
  if(!storeKeys && !ids) return;
1317
1346
 
1318
- len = (storeKeys === undefined) ? ids.length : storeKeys.length;
1347
+ len = (!storeKeys) ? ids.length : storeKeys.length;
1319
1348
 
1320
1349
  for(idx=0;idx<len;idx++) {
1321
1350
 
@@ -1333,8 +1362,9 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1333
1362
 
1334
1363
  if ((status == K.EMPTY) || (status == K.ERROR)) {
1335
1364
  throw K.NOT_FOUND_ERROR ;
1336
- }else{
1337
- if(status==K.READY_NEW){
1365
+ }
1366
+ else {
1367
+ if(status==K.READY_NEW) {
1338
1368
  this.writeStatus(storeKey, K.BUSY_CREATING);
1339
1369
  this.dataHashDidChange(storeKey, rev, YES);
1340
1370
  retCreate.push(storeKey);
@@ -1353,30 +1383,32 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1353
1383
  // ignore K.READY_CLEAN, K.BUSY_LOADING, K.BUSY_CREATING, K.BUSY_COMMITTING,
1354
1384
  // K.BUSY_REFRESH_CLEAN, K_BUSY_REFRESH_DIRTY, KBUSY_DESTROYING
1355
1385
  }
1356
- }
1357
-
1386
+ }
1387
+
1358
1388
  // now commit storekeys to dataSource
1359
- if (source) ret=source.commitRecords.call(source, this, retCreate, retUpdate, retDestroy);
1389
+ if (source) ret = source.commitRecords.call(source, this, retCreate, retUpdate, retDestroy, params);
1360
1390
  //remove all commited changes from changelog
1361
- if (ret && recordTypes===undefined && ids===undefined && storeKeys===this.changelog){
1362
- this.changelog=null;
1391
+ if (ret && !recordTypes && !ids && storeKeys===this.changelog){
1392
+ this.changelog = null;
1363
1393
  }
1364
1394
  return ret ;
1365
1395
  },
1366
1396
 
1367
1397
  /**
1368
- Commits the passed store key. Based on the current state of the
1398
+ Commits the passed store key or id. Based on the current state of the
1369
1399
  record, this will ask the data source to perform the appropriate action
1370
1400
  on the store key.
1371
1401
 
1372
1402
  You have to pass either the id or the storeKey otherwise it will return NO.
1373
1403
 
1374
- @param {String} id to id of the record to load
1375
1404
  @param {SC.Record} recordType the expected record type
1376
-
1377
- @returns {SC.Bool} if the action was succesful.
1405
+ @param {String} id the id of the record to commit
1406
+ @param {Number} storeKey the storeKey of the record to commit
1407
+ @param {Hash} params optional additonal params that will passed down
1408
+ to the data source
1409
+ @returns {SC.Bool} if the action was successful.
1378
1410
  */
1379
- commitRecord: function(recordType, id, storeKey) {
1411
+ commitRecord: function(recordType, id, storeKey, params) {
1380
1412
  var array = this._TMP_RETRIEVE_ARRAY,
1381
1413
  ret ;
1382
1414
  if (id === undefined && storeKey === undefined ) return NO;
@@ -1389,7 +1421,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1389
1421
  id = array;
1390
1422
  }
1391
1423
 
1392
- ret = this.commitRecords(recordType, id, storeKey);
1424
+ ret = this.commitRecords(recordType, id, storeKey, params);
1393
1425
  array.length = 0 ;
1394
1426
  return ret;
1395
1427
  },
@@ -1510,6 +1542,7 @@ SC.Store = SC.Object.extend( /** @scope SC.Store.prototype */ {
1510
1542
  ret[idx] = storeKey = recordType.storeKeyFor(id); // needed to cache
1511
1543
  this.pushRetrieve(recordType, id, dataHash, storeKey);
1512
1544
  }
1545
+
1513
1546
  // return storeKeys
1514
1547
  return ret ;
1515
1548
  },
@@ -8,7 +8,9 @@
8
8
  var store, fds, storeKey1,storeKey2;
9
9
 
10
10
  module("SC.FixturesDataSource", {
11
- setup: function() {
11
+ setup: function() {
12
+ SC.RunLoop.begin();
13
+
12
14
  var Sample = (window.Sample= SC.Object.create());
13
15
  Sample.File = SC.Record.extend({ test:'hello'});
14
16
 
@@ -26,7 +28,11 @@ module("SC.FixturesDataSource", {
26
28
  ];
27
29
 
28
30
  store = SC.Store.create().from(SC.Record.fixtures);
29
- }
31
+ },
32
+
33
+ teardown: function() {
34
+ SC.RunLoop.end();
35
+ }
30
36
  });
31
37
 
32
38
  test("Verify findAll() loads all fixture data", function() {
@@ -118,4 +124,4 @@ test("Using SC.Query on fetch()", function() {
118
124
  var storeKeys = fixtures.fetch(store, q);
119
125
  equals(storeKeys.length, 9, 'storeKeys length should be 9');
120
126
 
121
- });
127
+ });
@@ -9,7 +9,7 @@
9
9
  var storeKeys, rec;
10
10
  module("SC.ManyAttribute core methods", {
11
11
  setup: function() {
12
-
12
+ SC.RunLoop.begin();
13
13
  MyApp = SC.Object.create({
14
14
  store: SC.Store.create()
15
15
  });
@@ -47,6 +47,8 @@ module("SC.ManyAttribute core methods", {
47
47
  rec3 = MyApp.store.find(MyApp.Foo, 3);
48
48
  rec4 = MyApp.store.find(MyApp.Foo, 4);
49
49
  equals(rec.storeKey, storeKeys[0], 'should find record');
50
+
51
+ SC.RunLoop.end();
50
52
  }
51
53
  });
52
54
 
@@ -74,7 +76,10 @@ test("writing to a to-many relationship should update set guids", function() {
74
76
  equals(rec3.get('id'), 3, 'precond - should find record 3');
75
77
  equals(rec3.get('fooMany').objectAt(0), rec, 'should get rec1 instance for rec3.fooMany');
76
78
 
79
+ SC.RunLoop.begin();
77
80
  rec3.set('fooMany', [rec2, rec4]);
81
+ SC.RunLoop.end();
82
+
78
83
  equals(rec3.get('fooMany').objectAt(0), rec2, 'should get rec2 instance for rec3.fooMany');
79
84
  equals(rec3.get('fooMany').objectAt(1), rec4, 'should get rec2 instance for rec3.fooMany');
80
85
  });
@@ -5,11 +5,21 @@
5
5
  // ==========================================================================
6
6
  /*globals module ok equals same test MyApp */
7
7
 
8
- var MyApp;
8
+ var MyApp, dataSource;
9
9
  module("SC.Record core methods", {
10
10
  setup: function() {
11
+ dataSource = SC.DataSource.create({
12
+
13
+ gotParams: NO,
14
+ wasCommitted: NO,
15
+
16
+ createRecord: function(store, storeKey, params) {
17
+ this.wasCommitted = YES;
18
+ this.gotParams = params && params['param1'] ? YES: NO;
19
+ }});
20
+
11
21
  MyApp = SC.Object.create({
12
- store: SC.Store.create()
22
+ store: SC.Store.create().from(dataSource)
13
23
  }) ;
14
24
 
15
25
  MyApp.Foo = SC.Record.extend({});
@@ -17,14 +27,29 @@ module("SC.Record core methods", {
17
27
  foo: "bar",
18
28
  number: 123,
19
29
  bool: YES,
20
- array: [1,2,3]
30
+ array: [1,2,3],
31
+ guid: 1
21
32
  };
22
33
 
34
+ SC.RunLoop.begin();
23
35
  MyApp.foo = MyApp.store.createRecord(MyApp.Foo, MyApp.json);
36
+ SC.RunLoop.end();
24
37
 
25
38
  }
26
39
  });
27
40
 
28
41
  test("statusString", function() {
29
42
  equals(MyApp.foo.statusString(), 'READY_NEW', 'status string should be READY_NEW');
43
+ });
44
+
45
+ test("Can commitRecord() specific SC.Record instance", function() {
46
+
47
+ MyApp.foo.set('foo', 'foobar');
48
+
49
+ // commit the new record
50
+ MyApp.foo.commitRecord({ param1: 'value1' });
51
+
52
+ equals(dataSource.wasCommitted, YES, 'Record was committed');
53
+ equals(dataSource.gotParams, YES, 'Params were properly passed through commitRecord');
54
+
30
55
  });
@@ -8,6 +8,7 @@
8
8
  var MyFoo = null, callInfo ;
9
9
  module("SC.Record#destroy", {
10
10
  setup: function() {
11
+ SC.RunLoop.begin();
11
12
  MyApp = SC.Object.create({
12
13
  store: SC.Store.create()
13
14
  }) ;
@@ -30,16 +31,17 @@ module("SC.Record#destroy", {
30
31
  callInfo = SC.A(arguments) ; // save method call
31
32
  MyApp.store.__orig.apply(MyApp.store, arguments);
32
33
  };
34
+ SC.RunLoop.end();
33
35
  }
34
36
  });
35
37
 
36
38
  test("calling destroy on a newRecord will mark the record as destroyed and calls destroyRecords on the store", function() {
37
39
  equals(MyApp.foo.get('status'), SC.Record.READY_NEW, 'precond - status is READY_NEW');
38
-
40
+ SC.RunLoop.begin();
39
41
  MyApp.foo.destroy();
40
-
42
+ SC.RunLoop.end();
41
43
  same(callInfo, [null, null, MyApp.foo.storeKey], 'destroyRecords() should not be called');
42
-
44
+
43
45
  equals(MyApp.foo.get('status'), SC.Record.DESTROYED_CLEAN, 'status should be SC.Record.DESTROYED_CLEAN');
44
46
  });
45
47
 
@@ -50,9 +52,11 @@ test("calling destroy on existing record should call destroyRecord() on store",
50
52
  .dataHashDidChange(MyApp.foo.storeKey, null, YES);
51
53
 
52
54
  equals(MyApp.foo.get('status'), SC.Record.READY_CLEAN, 'precond - status is READY CLEAN');
53
-
55
+
56
+ SC.RunLoop.begin();
54
57
  MyApp.foo.destroy();
55
-
58
+ SC.RunLoop.end();
59
+
56
60
  same(callInfo, [null, null, MyApp.foo.storeKey], 'destroyRecord() should not be called');
57
61
  equals(MyApp.foo.get('status'), SC.Record.DESTROYED_DIRTY, 'status should be SC.Record.DESTROYED_DIRTY');
58
62
  });
@@ -60,10 +64,14 @@ test("calling destroy on existing record should call destroyRecord() on store",
60
64
  test("calling destroy on a record that is already destroyed should do nothing", function() {
61
65
 
62
66
  // destroy once
67
+ SC.RunLoop.begin();
63
68
  MyApp.foo.destroy();
69
+ SC.RunLoop.end();
64
70
  equals(MyApp.foo.get('status'), SC.Record.DESTROYED_CLEAN, 'status should be DESTROYED_CLEAN');
65
71
 
72
+ SC.RunLoop.begin();
66
73
  MyApp.foo.destroy();
74
+ SC.RunLoop.end();
67
75
  equals(MyApp.foo.get('status'), SC.Record.DESTROYED_CLEAN, 'status should be DESTROYED_CLEAN');
68
76
  });
69
77