// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2010 Evin Grano // Portions ©2008-2011 Apple Inc. All rights reserved. // License: Licensed under MIT license (see license.js) // ==========================================================================

sc_require('models/record'); sc_require('models/record_attribute'); sc_require('models/child_attribute'); sc_require('system/child_array');

/** @class

ChildrenAttribute is a subclass of ChildAttribute and handles to-many
relationships for child records.

When setting ( `.set()` ) the value of a toMany attribute, make sure
to pass in an array of SC.Record objects.

There are many ways you can configure a ChildrenAttribute:

    contacts: SC.ChildrenAttribute.attr('SC.Child');

@extends SC.RecordAttribute
@since SproutCore 1.0

*/ SC.ChildrenAttribute = SC.ChildAttribute.extend(

/** @scope SC.ChildrenAttribute.prototype */ {

// ..........................................................
// LOW-LEVEL METHODS
//

/**  @private - adapted for to many relationship */
toType: function (record, key, value) {
  var attrKey   = this.get('key') || key,
      arrayKey  = SC.keyFor('__kidsArray__', SC.guidFor(this)),
      ret       = record[arrayKey],
      recordType  = this.get('typeClass'),
      rel;

  // lazily create a ChildArray one time.  after that always return the
  // same object.
  if (!ret) {
    ret = SC.ChildArray.create({
      record: record,
      propertyName: attrKey,
      defaultRecordType: recordType
    });

    record[arrayKey] = ret; // cache on record

    // Make sure the child array gets notified of changes to the parent record.
    rel = record.get('relationships');
    if (!rel) record.set('relationships', rel = []);
    rel.push(ret);
  }

  return ret;
},

// Default fromType is just returning itself
fromType: function (record, key, value) {
  var sk, store,
      arrayKey = SC.keyFor('__kidsArray__', SC.guidFor(this)),
      ret = record[arrayKey];

  if (record) {
    record.writeAttribute(key, value);

    // If the SC.ChildArray already exists, indicate that its backing content has changed.
    if (ret) ret = ret.recordPropertyDidChange();
  }

  return ret;
}

/** UNUSED. This seems to have no effect on SC.ChildArray usage. Kept here for quick reference.
  The core handler.  Called from the property.
  @param {SC.Record} record the record instance
  @param {String} key the key used to access this attribute on the record
  @param {Object} value the property value if called as a setter
  @returns {Object} property value
*/
// call: function(record, key, value) {
//   var attrKey = this.get('key') || key, cRef,
//       cacheKey = SC.keyFor('__kid__', SC.guidFor(this));
//   if (value !== undefined) {
//     value = this.fromType(record, key, value) ; // convert to attribute.
//   } else {
//     value = record.readAttribute(attrKey);
//     if (SC.none(value) && (value = this.get('defaultValue'))) {
//       if (typeof value === SC.T_FUNCTION) {
//         value = this.defaultValue(record, key, this);
//         // write default value so it doesn't have to be executed again
//         if (record.attributes()) {
//           // Check for an array
//           if (value instanceof Array) {
//             // Instantiate the construct and replace all of the content.
//             value = this.toType(record, key, value).replace(0, value.length, value);
//           } else {
//             record.writeAttribute(attrKey, value, true);
//           }
//         }
//       }
//     } else value = this.toType(record, key, value);
//   }

//   return value ;
// }

});