1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2010 Evin Grano 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 sc_require('models/record'); 9 sc_require('models/record_attribute'); 10 sc_require('models/child_attribute'); 11 sc_require('system/child_array'); 12 13 /** @class 14 15 ChildrenAttribute is a subclass of ChildAttribute and handles to-many 16 relationships for child records. 17 18 When setting ( `.set()` ) the value of a toMany attribute, make sure 19 to pass in an array of SC.Record objects. 20 21 There are many ways you can configure a ChildrenAttribute: 22 23 contacts: SC.ChildrenAttribute.attr('SC.Child'); 24 25 @extends SC.RecordAttribute 26 @since SproutCore 1.0 27 */ 28 SC.ChildrenAttribute = SC.ChildAttribute.extend( 29 /** @scope SC.ChildrenAttribute.prototype */ { 30 31 // .......................................................... 32 // LOW-LEVEL METHODS 33 // 34 35 /** @private - adapted for to many relationship */ 36 toType: function (record, key, value) { 37 var attrKey = this.get('key') || key, 38 arrayKey = SC.keyFor('__kidsArray__', SC.guidFor(this)), 39 ret = record[arrayKey], 40 recordType = this.get('typeClass'), 41 rel; 42 43 // lazily create a ChildArray one time. after that always return the 44 // same object. 45 if (!ret) { 46 ret = SC.ChildArray.create({ 47 record: record, 48 propertyName: attrKey, 49 defaultRecordType: recordType 50 }); 51 52 record[arrayKey] = ret; // cache on record 53 54 // Make sure the child array gets notified of changes to the parent record. 55 rel = record.get('relationships'); 56 if (!rel) record.set('relationships', rel = []); 57 rel.push(ret); 58 } 59 60 return ret; 61 }, 62 63 // Default fromType is just returning itself 64 fromType: function (record, key, value) { 65 var sk, store, 66 arrayKey = SC.keyFor('__kidsArray__', SC.guidFor(this)), 67 ret = record[arrayKey]; 68 69 if (record) { 70 record.writeAttribute(key, value); 71 72 // If the SC.ChildArray already exists, indicate that its backing content has changed. 73 if (ret) ret = ret.recordPropertyDidChange(); 74 } 75 76 return ret; 77 } 78 79 /** UNUSED. This seems to have no effect on SC.ChildArray usage. Kept here for quick reference. 80 The core handler. Called from the property. 81 @param {SC.Record} record the record instance 82 @param {String} key the key used to access this attribute on the record 83 @param {Object} value the property value if called as a setter 84 @returns {Object} property value 85 */ 86 // call: function(record, key, value) { 87 // var attrKey = this.get('key') || key, cRef, 88 // cacheKey = SC.keyFor('__kid__', SC.guidFor(this)); 89 // if (value !== undefined) { 90 // value = this.fromType(record, key, value) ; // convert to attribute. 91 // } else { 92 // value = record.readAttribute(attrKey); 93 // if (SC.none(value) && (value = this.get('defaultValue'))) { 94 // if (typeof value === SC.T_FUNCTION) { 95 // value = this.defaultValue(record, key, this); 96 // // write default value so it doesn't have to be executed again 97 // if (record.attributes()) { 98 // // Check for an array 99 // if (value instanceof Array) { 100 // // Instantiate the construct and replace all of the content. 101 // value = this.toType(record, key, value).replace(0, value.length, value); 102 // } else { 103 // record.writeAttribute(attrKey, value, true); 104 // } 105 // } 106 // } 107 // } else value = this.toType(record, key, value); 108 // } 109 110 // return value ; 111 // } 112 113 }); 114 115 116