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