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 11 /** @class 12 13 ChildAttribute is a subclass of `RecordAttribute` and handles to-one 14 relationships for child records. 15 16 When setting ( `.set()` ) the value of a toMany attribute, make sure 17 to pass in an array of `SC.Record` objects. 18 19 There are many ways you can configure a ManyAttribute: 20 21 contacts: SC.ChildAttribute.attr('SC.Child'); 22 23 @extends SC.RecordAttribute 24 @since SproutCore 1.0 25 */ 26 SC.ChildAttribute = SC.RecordAttribute.extend( 27 /** @scope SC.ChildAttribute.prototype */ { 28 29 isNestedRecordTransform: YES, 30 31 // .......................................................... 32 // LOW-LEVEL METHODS 33 // 34 35 /** @private - adapted for to one relationship */ 36 toType: function(record, key, value) { 37 var ret = null, rel, 38 recordType = this.get('typeClass'); 39 40 if (!record) { 41 throw new Error('SC.Child: Error during transform: Unable to retrieve parent record.'); 42 } 43 if (!SC.none(value)) ret = record.registerNestedRecord(value, key); 44 45 return ret; 46 }, 47 48 // Default fromType is just returning itself 49 fromType: function(record, key, value) { 50 var sk, store, ret; 51 52 if (record) { 53 // Unregister the old child (nested) record. 54 if (record.readAttribute(key)) { 55 record.unregisterNestedRecord(key); 56 } 57 58 if (SC.none(value)) { 59 // Handle null value. 60 record.writeAttribute(key, value); 61 ret = value; 62 } else { 63 // Register the nested record with this record (the parent). 64 ret = record.registerNestedRecord(value, key); 65 66 if (ret) { 67 // Write the data hash of the nested record to the store. 68 sk = ret.get('storeKey'); 69 store = ret.get('store'); 70 record.writeAttribute(key, store.readDataHash(sk)); 71 } else if (value) { 72 // If registration failed, just write the value. 73 record.writeAttribute(key, value); 74 } 75 } 76 } 77 78 return ret; 79 }, 80 81 /** 82 The core handler. Called from the property. 83 @param {SC.Record} record the record instance 84 @param {String} key the key used to access this attribute on the record 85 @param {Object} value the property value if called as a setter 86 @returns {Object} property value 87 */ 88 call: function(record, key, value) { 89 var attrKey = this.get('key') || key; 90 if (value !== undefined) { 91 value = this.fromType(record, key, value) ; // convert to attribute. 92 } else { 93 value = record.readAttribute(attrKey); 94 if (SC.none(value) && (value = this.get('defaultValue'))) { 95 if (typeof value === SC.T_FUNCTION) { 96 value = this.defaultValue(record, key, this); 97 // write default value so it doesn't have to be executed again 98 if(record.attributes()) record.writeAttribute(attrKey, value, true); 99 } 100 } else value = this.toType(record, key, value); 101 } 102 103 return value ; 104 } 105 }); 106 107 108