Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Model.html
index fce03bc..f199d14 100644 (file)
@@ -3,8 +3,8 @@
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
-  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
   <style type="text/css">
     .highlight { display: block; background-color: #ddd; }
   </style>
 <body onload="prettyPrint(); highlight();">
   <pre class="prettyprint lang-js"><span id='Ext-data-Model-method-constructor'><span id='Ext-data-Model'>/**
 </span></span> * @author Ed Spencer
- * @class Ext.data.Model
  *
- * &lt;p&gt;A Model represents some object that your application manages. For example, one might define a Model for Users, Products,
- * Cars, or any other real-world object that we want to model in the system. Models are registered via the {@link Ext.ModelManager model manager},
- * and are used by {@link Ext.data.Store stores}, which are in turn used by many of the data-bound components in Ext.&lt;/p&gt;
+ * A Model represents some object that your application manages. For example, one might define a Model for Users,
+ * Products, Cars, or any other real-world object that we want to model in the system. Models are registered via the
+ * {@link Ext.ModelManager model manager}, and are used by {@link Ext.data.Store stores}, which are in turn used by many
+ * of the data-bound components in Ext.
  *
- * &lt;p&gt;Models are defined as a set of fields and any arbitrary methods and properties relevant to the model. For example:&lt;/p&gt;
+ * Models are defined as a set of fields and any arbitrary methods and properties relevant to the model. For example:
  *
-&lt;pre&gt;&lt;code&gt;
-Ext.define('User', {
-    extend: 'Ext.data.Model',
-    fields: [
-        {name: 'name',  type: 'string'},
-        {name: 'age',   type: 'int'},
-        {name: 'phone', type: 'string'},
-        {name: 'alive', type: 'boolean', defaultValue: true}
-    ],
-
-    changeName: function() {
-        var oldName = this.get('name'),
-            newName = oldName + &quot; The Barbarian&quot;;
-
-        this.set('name', newName);
-    }
-});
-&lt;/code&gt;&lt;/pre&gt;
-*
-* &lt;p&gt;The fields array is turned into a {@link Ext.util.MixedCollection MixedCollection} automatically by the {@link Ext.ModelManager ModelManager}, and all
-* other functions and properties are copied to the new Model's prototype.&lt;/p&gt;
-*
-* &lt;p&gt;Now we can create instances of our User model and call any model logic we defined:&lt;/p&gt;
-*
-&lt;pre&gt;&lt;code&gt;
-var user = Ext.ModelManager.create({
-    name : 'Conan',
-    age  : 24,
-    phone: '555-555-5555'
-}, 'User');
-
-user.changeName();
-user.get('name'); //returns &quot;Conan The Barbarian&quot;
-&lt;/code&gt;&lt;/pre&gt;
+ *     Ext.define('User', {
+ *         extend: 'Ext.data.Model',
+ *         fields: [
+ *             {name: 'name',  type: 'string'},
+ *             {name: 'age',   type: 'int'},
+ *             {name: 'phone', type: 'string'},
+ *             {name: 'alive', type: 'boolean', defaultValue: true}
+ *         ],
  *
- * &lt;p&gt;&lt;u&gt;Validations&lt;/u&gt;&lt;/p&gt;
+ *         changeName: function() {
+ *             var oldName = this.get('name'),
+ *                 newName = oldName + &quot; The Barbarian&quot;;
  *
- * &lt;p&gt;Models have built-in support for validations, which are executed against the validator functions in
- * {@link Ext.data.validations} ({@link Ext.data.validations see all validation functions}). Validations are easy to add to models:&lt;/p&gt;
+ *             this.set('name', newName);
+ *         }
+ *     });
  *
-&lt;pre&gt;&lt;code&gt;
-Ext.define('User', {
-    extend: 'Ext.data.Model',
-    fields: [
-        {name: 'name',     type: 'string'},
-        {name: 'age',      type: 'int'},
-        {name: 'phone',    type: 'string'},
-        {name: 'gender',   type: 'string'},
-        {name: 'username', type: 'string'},
-        {name: 'alive',    type: 'boolean', defaultValue: true}
-    ],
-
-    validations: [
-        {type: 'presence',  field: 'age'},
-        {type: 'length',    field: 'name',     min: 2},
-        {type: 'inclusion', field: 'gender',   list: ['Male', 'Female']},
-        {type: 'exclusion', field: 'username', list: ['Admin', 'Operator']},
-        {type: 'format',    field: 'username', matcher: /([a-z]+)[0-9]{2,3}/}
-    ]
-});
-&lt;/code&gt;&lt;/pre&gt;
+ * The fields array is turned into a {@link Ext.util.MixedCollection MixedCollection} automatically by the {@link
+ * Ext.ModelManager ModelManager}, and all other functions and properties are copied to the new Model's prototype.
  *
- * &lt;p&gt;The validations can be run by simply calling the {@link #validate} function, which returns a {@link Ext.data.Errors}
- * object:&lt;/p&gt;
+ * Now we can create instances of our User model and call any model logic we defined:
  *
-&lt;pre&gt;&lt;code&gt;
-var instance = Ext.ModelManager.create({
-    name: 'Ed',
-    gender: 'Male',
-    username: 'edspencer'
-}, 'User');
-
-var errors = instance.validate();
-&lt;/code&gt;&lt;/pre&gt;
+ *     var user = Ext.create('User', {
+ *         name : 'Conan',
+ *         age  : 24,
+ *         phone: '555-555-5555'
+ *     });
  *
- * &lt;p&gt;&lt;u&gt;Associations&lt;/u&gt;&lt;/p&gt;
+ *     user.changeName();
+ *     user.get('name'); //returns &quot;Conan The Barbarian&quot;
  *
- * &lt;p&gt;Models can have associations with other Models via {@link Ext.data.BelongsToAssociation belongsTo} and
- * {@link Ext.data.HasManyAssociation hasMany} associations. For example, let's say we're writing a blog administration
- * application which deals with Users, Posts and Comments. We can express the relationships between these models like this:&lt;/p&gt;
+ * # Validations
  *
-&lt;pre&gt;&lt;code&gt;
-Ext.define('Post', {
-    extend: 'Ext.data.Model',
-    fields: ['id', 'user_id'],
-
-    belongsTo: 'User',
-    hasMany  : {model: 'Comment', name: 'comments'}
-});
-
-Ext.define('Comment', {
-    extend: 'Ext.data.Model',
-    fields: ['id', 'user_id', 'post_id'],
-
-    belongsTo: 'Post'
-});
-
-Ext.define('User', {
-    extend: 'Ext.data.Model',
-    fields: ['id'],
-
-    hasMany: [
-        'Post',
-        {model: 'Comment', name: 'comments'}
-    ]
-});
-&lt;/code&gt;&lt;/pre&gt;
+ * Models have built-in support for validations, which are executed against the validator functions in {@link
+ * Ext.data.validations} ({@link Ext.data.validations see all validation functions}). Validations are easy to add to
+ * models:
  *
- * &lt;p&gt;See the docs for {@link Ext.data.BelongsToAssociation} and {@link Ext.data.HasManyAssociation} for details on the usage
- * and configuration of associations. Note that associations can also be specified like this:&lt;/p&gt;
+ *     Ext.define('User', {
+ *         extend: 'Ext.data.Model',
+ *         fields: [
+ *             {name: 'name',     type: 'string'},
+ *             {name: 'age',      type: 'int'},
+ *             {name: 'phone',    type: 'string'},
+ *             {name: 'gender',   type: 'string'},
+ *             {name: 'username', type: 'string'},
+ *             {name: 'alive',    type: 'boolean', defaultValue: true}
+ *         ],
  *
-&lt;pre&gt;&lt;code&gt;
-Ext.define('User', {
-    extend: 'Ext.data.Model',
-    fields: ['id'],
-
-    associations: [
-        {type: 'hasMany', model: 'Post',    name: 'posts'},
-        {type: 'hasMany', model: 'Comment', name: 'comments'}
-    ]
-});
-&lt;/code&gt;&lt;/pre&gt;
+ *         validations: [
+ *             {type: 'presence',  field: 'age'},
+ *             {type: 'length',    field: 'name',     min: 2},
+ *             {type: 'inclusion', field: 'gender',   list: ['Male', 'Female']},
+ *             {type: 'exclusion', field: 'username', list: ['Admin', 'Operator']},
+ *             {type: 'format',    field: 'username', matcher: /([a-z]+)[0-9]{2,3}/}
+ *         ]
+ *     });
  *
- * &lt;p&gt;&lt;u&gt;Using a Proxy&lt;/u&gt;&lt;/p&gt;
+ * The validations can be run by simply calling the {@link #validate} function, which returns a {@link Ext.data.Errors}
+ * object:
  *
- * &lt;p&gt;Models are great for representing types of data and relationships, but sooner or later we're going to want to
- * load or save that data somewhere. All loading and saving of data is handled via a {@link Ext.data.proxy.Proxy Proxy},
- * which can be set directly on the Model:&lt;/p&gt;
+ *     var instance = Ext.create('User', {
+ *         name: 'Ed',
+ *         gender: 'Male',
+ *         username: 'edspencer'
+ *     });
  *
-&lt;pre&gt;&lt;code&gt;
-Ext.define('User', {
-    extend: 'Ext.data.Model',
-    fields: ['id', 'name', 'email'],
-
-    proxy: {
-        type: 'rest',
-        url : '/users'
-    }
-});
-&lt;/code&gt;&lt;/pre&gt;
+ *     var errors = instance.validate();
  *
- * &lt;p&gt;Here we've set up a {@link Ext.data.proxy.Rest Rest Proxy}, which knows how to load and save data to and from a
- * RESTful backend. Let's see how this works:&lt;/p&gt;
+ * # Associations
  *
-&lt;pre&gt;&lt;code&gt;
-var user = Ext.ModelManager.create({name: 'Ed Spencer', email: 'ed@sencha.com'}, 'User');
-
-user.save(); //POST /users
-&lt;/code&gt;&lt;/pre&gt;
+ * Models can have associations with other Models via {@link Ext.data.BelongsToAssociation belongsTo} and {@link
+ * Ext.data.HasManyAssociation hasMany} associations. For example, let's say we're writing a blog administration
+ * application which deals with Users, Posts and Comments. We can express the relationships between these models like
+ * this:
  *
- * &lt;p&gt;Calling {@link #save} on the new Model instance tells the configured RestProxy that we wish to persist this
- * Model's data onto our server. RestProxy figures out that this Model hasn't been saved before because it doesn't
- * have an id, and performs the appropriate action - in this case issuing a POST request to the url we configured
- * (/users). We configure any Proxy on any Model and always follow this API - see {@link Ext.data.proxy.Proxy} for a full
- * list.&lt;/p&gt;
+ *     Ext.define('Post', {
+ *         extend: 'Ext.data.Model',
+ *         fields: ['id', 'user_id'],
  *
- * &lt;p&gt;Loading data via the Proxy is equally easy:&lt;/p&gt;
+ *         belongsTo: 'User',
+ *         hasMany  : {model: 'Comment', name: 'comments'}
+ *     });
  *
-&lt;pre&gt;&lt;code&gt;
-//get a reference to the User model class
-var User = Ext.ModelManager.getModel('User');
-
-//Uses the configured RestProxy to make a GET request to /users/123
-User.load(123, {
-    success: function(user) {
-        console.log(user.getId()); //logs 123
-    }
-});
-&lt;/code&gt;&lt;/pre&gt;
+ *     Ext.define('Comment', {
+ *         extend: 'Ext.data.Model',
+ *         fields: ['id', 'user_id', 'post_id'],
  *
- * &lt;p&gt;Models can also be updated and destroyed easily:&lt;/p&gt;
+ *         belongsTo: 'Post'
+ *     });
  *
-&lt;pre&gt;&lt;code&gt;
-//the user Model we loaded in the last snippet:
-user.set('name', 'Edward Spencer');
-
-//tells the Proxy to save the Model. In this case it will perform a PUT request to /users/123 as this Model already has an id
-user.save({
-    success: function() {
-        console.log('The User was updated');
-    }
-});
-
-//tells the Proxy to destroy the Model. Performs a DELETE request to /users/123
-user.destroy({
-    success: function() {
-        console.log('The User was destroyed!');
-    }
-});
-&lt;/code&gt;&lt;/pre&gt;
+ *     Ext.define('User', {
+ *         extend: 'Ext.data.Model',
+ *         fields: ['id'],
  *
- * &lt;p&gt;&lt;u&gt;Usage in Stores&lt;/u&gt;&lt;/p&gt;
+ *         hasMany: [
+ *             'Post',
+ *             {model: 'Comment', name: 'comments'}
+ *         ]
+ *     });
  *
- * &lt;p&gt;It is very common to want to load a set of Model instances to be displayed and manipulated in the UI. We do this
- * by creating a {@link Ext.data.Store Store}:&lt;/p&gt;
+ * See the docs for {@link Ext.data.BelongsToAssociation} and {@link Ext.data.HasManyAssociation} for details on the
+ * usage and configuration of associations. Note that associations can also be specified like this:
  *
-&lt;pre&gt;&lt;code&gt;
-var store = new Ext.data.Store({
-    model: 'User'
-});
-
-//uses the Proxy we set up on Model to load the Store data
-store.load();
-&lt;/code&gt;&lt;/pre&gt;
+ *     Ext.define('User', {
+ *         extend: 'Ext.data.Model',
+ *         fields: ['id'],
+ *
+ *         associations: [
+ *             {type: 'hasMany', model: 'Post',    name: 'posts'},
+ *             {type: 'hasMany', model: 'Comment', name: 'comments'}
+ *         ]
+ *     });
+ *
+ * # Using a Proxy
+ *
+ * Models are great for representing types of data and relationships, but sooner or later we're going to want to load or
+ * save that data somewhere. All loading and saving of data is handled via a {@link Ext.data.proxy.Proxy Proxy}, which
+ * can be set directly on the Model:
  *
- * &lt;p&gt;A Store is just a collection of Model instances - usually loaded from a server somewhere. Store can also maintain
- * a set of added, updated and removed Model instances to be synchronized with the server via the Proxy. See the
- * {@link Ext.data.Store Store docs} for more information on Stores.&lt;/p&gt;
+ *     Ext.define('User', {
+ *         extend: 'Ext.data.Model',
+ *         fields: ['id', 'name', 'email'],
+ *
+ *         proxy: {
+ *             type: 'rest',
+ *             url : '/users'
+ *         }
+ *     });
+ *
+ * Here we've set up a {@link Ext.data.proxy.Rest Rest Proxy}, which knows how to load and save data to and from a
+ * RESTful backend. Let's see how this works:
+ *
+ *     var user = Ext.create('User', {name: 'Ed Spencer', email: 'ed@sencha.com'});
+ *
+ *     user.save(); //POST /users
+ *
+ * Calling {@link #save} on the new Model instance tells the configured RestProxy that we wish to persist this Model's
+ * data onto our server. RestProxy figures out that this Model hasn't been saved before because it doesn't have an id,
+ * and performs the appropriate action - in this case issuing a POST request to the url we configured (/users). We
+ * configure any Proxy on any Model and always follow this API - see {@link Ext.data.proxy.Proxy} for a full list.
+ *
+ * Loading data via the Proxy is equally easy:
+ *
+ *     //get a reference to the User model class
+ *     var User = Ext.ModelManager.getModel('User');
+ *
+ *     //Uses the configured RestProxy to make a GET request to /users/123
+ *     User.load(123, {
+ *         success: function(user) {
+ *             console.log(user.getId()); //logs 123
+ *         }
+ *     });
+ *
+ * Models can also be updated and destroyed easily:
+ *
+ *     //the user Model we loaded in the last snippet:
+ *     user.set('name', 'Edward Spencer');
+ *
+ *     //tells the Proxy to save the Model. In this case it will perform a PUT request to /users/123 as this Model already has an id
+ *     user.save({
+ *         success: function() {
+ *             console.log('The User was updated');
+ *         }
+ *     });
+ *
+ *     //tells the Proxy to destroy the Model. Performs a DELETE request to /users/123
+ *     user.destroy({
+ *         success: function() {
+ *             console.log('The User was destroyed!');
+ *         }
+ *     });
+ *
+ * # Usage in Stores
+ *
+ * It is very common to want to load a set of Model instances to be displayed and manipulated in the UI. We do this by
+ * creating a {@link Ext.data.Store Store}:
+ *
+ *     var store = Ext.create('Ext.data.Store', {
+ *         model: 'User'
+ *     });
+ *
+ *     //uses the Proxy we set up on Model to load the Store data
+ *     store.load();
+ *
+ * A Store is just a collection of Model instances - usually loaded from a server somewhere. Store can also maintain a
+ * set of added, updated and removed Model instances to be synchronized with the server via the Proxy. See the {@link
+ * Ext.data.Store Store docs} for more information on Stores.
  *
  * @constructor
+ * Creates new Model instance.
  * @param {Object} data An object containing keys corresponding to this model's fields, and their associated values
  * @param {Number} id (optional) Unique ID to assign to this model instance
  */
 Ext.define('Ext.data.Model', {
     alternateClassName: 'Ext.data.Record',
-    
+
     mixins: {
         observable: 'Ext.util.Observable'
     },
 
     requires: [
         'Ext.ModelManager',
+        'Ext.data.IdGenerator',
         'Ext.data.Field',
         'Ext.data.Errors',
         'Ext.data.Operation',
@@ -269,6 +250,7 @@ Ext.define('Ext.data.Model', {
                 associations = data.associations || [],
                 belongsTo = data.belongsTo,
                 hasMany = data.hasMany,
+                idgen = data.idgen,
 
                 fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
                     return field.name;
@@ -307,6 +289,10 @@ Ext.define('Ext.data.Model', {
 
             data.fields = fieldsMixedCollection;
 
+            if (idgen) {
+                data.idgen = Ext.data.IdGenerator.get(idgen);
+            }
+
             //associations can be specified in the more convenient format (e.g. not inside an 'associations' array).
             //we support that here
             if (belongsTo) {
@@ -390,10 +376,13 @@ Ext.define('Ext.data.Model', {
     },
 
     inheritableStatics: {
-<span id='Ext-data-Model-method-setProxy'>        /**
-</span>         * Sets the Proxy to use for this model. Accepts any options that can be accepted by {@link Ext#createByAlias Ext.createByAlias}
+<span id='Ext-data-Model-static-method-setProxy'>        /**
+</span>         * Sets the Proxy to use for this model. Accepts any options that can be accepted by
+         * {@link Ext#createByAlias Ext.createByAlias}.
          * @param {String/Object/Ext.data.proxy.Proxy} proxy The proxy
+         * @return {Ext.data.proxy.Proxy}
          * @static
+         * @inheritable
          */
         setProxy: function(proxy) {
             //make sure we have an Ext.data.proxy.Proxy object
@@ -411,43 +400,45 @@ Ext.define('Ext.data.Model', {
             return proxy;
         },
 
-<span id='Ext-data-Model-method-getProxy'>        /**
+<span id='Ext-data-Model-static-method-getProxy'>        /**
 </span>         * Returns the configured Proxy for this Model
          * @return {Ext.data.proxy.Proxy} The proxy
+         * @static
+         * @inheritable
          */
         getProxy: function() {
             return this.proxy;
         },
 
-<span id='Ext-data-Model-method-load'>        /**
-</span>         * &lt;b&gt;Static&lt;/b&gt;. Asynchronously loads a model instance by id. Sample usage:
-    &lt;pre&gt;&lt;code&gt;
-    MyApp.User = Ext.define('User', {
-        extend: 'Ext.data.Model',
-        fields: [
-            {name: 'id', type: 'int'},
-            {name: 'name', type: 'string'}
-        ]
-    });
-
-    MyApp.User.load(10, {
-        scope: this,
-        failure: function(record, operation) {
-            //do something if the load failed
-        },
-        success: function(record, operation) {
-            //do something if the load succeeded
-        },
-        callback: function(record, operation) {
-            //do something whether the load succeeded or failed
-        }
-    });
-    &lt;/code&gt;&lt;/pre&gt;
+<span id='Ext-data-Model-static-method-load'>        /**
+</span>         * Asynchronously loads a model instance by id. Sample usage:
+         *
+         *     MyApp.User = Ext.define('User', {
+         *         extend: 'Ext.data.Model',
+         *         fields: [
+         *             {name: 'id', type: 'int'},
+         *             {name: 'name', type: 'string'}
+         *         ]
+         *     });
+         *
+         *     MyApp.User.load(10, {
+         *         scope: this,
+         *         failure: function(record, operation) {
+         *             //do something if the load failed
+         *         },
+         *         success: function(record, operation) {
+         *             //do something if the load succeeded
+         *         },
+         *         callback: function(record, operation) {
+         *             //do something whether the load succeeded or failed
+         *         }
+         *     });
+         *
          * @param {Number} id The id of the model to load
-         * @param {Object} config Optional config object containing success, failure and callback functions, plus optional scope
-         * @member Ext.data.Model
-         * @method load
+         * @param {Object} config (optional) config object containing success, failure and callback functions, plus
+         * optional scope
          * @static
+         * @inheritable
          */
         load: function(id, config) {
             config = Ext.apply({}, config);
@@ -482,18 +473,16 @@ Ext.define('Ext.data.Model', {
         REJECT : 'reject',
         COMMIT : 'commit',
 
-<span id='Ext-data-Model-method-id'>        /**
-</span>         * Generates a sequential id. This method is typically called when a record is {@link #create}d
-         * and {@link #Record no id has been specified}. The id will automatically be assigned
-         * to the record. The returned id takes the form:
-         * &lt;tt&gt;&amp;#123;PREFIX}-&amp;#123;AUTO_ID}&lt;/tt&gt;.&lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
-         * &lt;li&gt;&lt;b&gt;&lt;tt&gt;PREFIX&lt;/tt&gt;&lt;/b&gt; : String&lt;p class=&quot;sub-desc&quot;&gt;&lt;tt&gt;Ext.data.Model.PREFIX&lt;/tt&gt;
-         * (defaults to &lt;tt&gt;'ext-record'&lt;/tt&gt;)&lt;/p&gt;&lt;/li&gt;
-         * &lt;li&gt;&lt;b&gt;&lt;tt&gt;AUTO_ID&lt;/tt&gt;&lt;/b&gt; : String&lt;p class=&quot;sub-desc&quot;&gt;&lt;tt&gt;Ext.data.Model.AUTO_ID&lt;/tt&gt;
-         * (defaults to &lt;tt&gt;1&lt;/tt&gt; initially)&lt;/p&gt;&lt;/li&gt;
-         * &lt;/ul&gt;&lt;/div&gt;
-         * @param {Ext.data.Model} rec The record being created.  The record does not exist, it's a {@link #phantom}.
-         * @return {String} auto-generated string id, &lt;tt&gt;&quot;ext-record-i++'&lt;/tt&gt;;
+<span id='Ext-data-Model-static-method-id'>        /**
+</span>         * Generates a sequential id. This method is typically called when a record is {@link Ext#create
+         * create}d and {@link #constructor no id has been specified}. The id will automatically be assigned to the
+         * record. The returned id takes the form: {PREFIX}-{AUTO_ID}.
+         *
+         * - **PREFIX** : String - Ext.data.Model.PREFIX (defaults to 'ext-record')
+         * - **AUTO_ID** : String - Ext.data.Model.AUTO_ID (defaults to 1 initially)
+         *
+         * @param {Ext.data.Model} rec The record being created. The record does not exist, it's a {@link #phantom}.
+         * @return {String} auto-generated string id, `&quot;ext-record-i++&quot;`;
          * @static
          */
         id: function(rec) {
@@ -503,23 +492,98 @@ Ext.define('Ext.data.Model', {
             return id;
         }
     },
-    
+
+<span id='Ext-data-Model-cfg-idgen'>    /**
+</span>     * @cfg {String/Object} idgen
+     * The id generator to use for this model. The default id generator does not generate
+     * values for the {@link #idProperty}.
+     *
+     * This can be overridden at the model level to provide a custom generator for a model.
+     * The simplest form of this would be:
+     *
+     *      Ext.define('MyApp.data.MyModel', {
+     *          extend: 'Ext.data.Model',
+     *          requires: ['Ext.data.SequentialIdGenerator'],
+     *          idgen: 'sequential',
+     *          ...
+     *      });
+     *
+     * The above would generate {@link Ext.data.SequentialIdGenerator sequential} id's such
+     * as 1, 2, 3 etc..
+     *
+     * Another useful id generator is {@link Ext.data.UuidGenerator}:
+     *
+     *      Ext.define('MyApp.data.MyModel', {
+     *          extend: 'Ext.data.Model',
+     *          requires: ['Ext.data.UuidGenerator'],
+     *          idgen: 'uuid',
+     *          ...
+     *      });
+     *
+     * An id generation can also be further configured:
+     *
+     *      Ext.define('MyApp.data.MyModel', {
+     *          extend: 'Ext.data.Model',
+     *          idgen: {
+     *              type: 'sequential',
+     *              seed: 1000,
+     *              prefix: 'ID_'
+     *          }
+     *      });
+     *
+     * The above would generate id's such as ID_1000, ID_1001, ID_1002 etc..
+     *
+     * If multiple models share an id space, a single generator can be shared:
+     *
+     *      Ext.define('MyApp.data.MyModelX', {
+     *          extend: 'Ext.data.Model',
+     *          idgen: {
+     *              type: 'sequential',
+     *              id: 'xy'
+     *          }
+     *      });
+     *
+     *      Ext.define('MyApp.data.MyModelY', {
+     *          extend: 'Ext.data.Model',
+     *          idgen: {
+     *              type: 'sequential',
+     *              id: 'xy'
+     *          }
+     *      });
+     *
+     * For more complex, shared id generators, a custom generator is the best approach.
+     * See {@link Ext.data.IdGenerator} for details on creating custom id generators.
+     *
+     * @markdown
+     */
+    idgen: {
+        isGenerator: true,
+        type: 'default',
+
+        generate: function () {
+            return null;
+        },
+        getRecId: function (rec) {
+            return rec.modelName + '-' + rec.internalId;
+        }
+    },
+
 <span id='Ext-data-Model-property-editing'>    /**
-</span>     * Internal flag used to track whether or not the model instance is currently being edited. Read-only
-     * @property editing
-     * @type Boolean
+</span>     * @property {Boolean} editing
+     * Internal flag used to track whether or not the model instance is currently being edited. Read-only.
      */
     editing : false,
 
 <span id='Ext-data-Model-property-dirty'>    /**
-</span>     * Readonly flag - true if this Record has been modified.
-     * @type Boolean
+</span>     * @property {Boolean} dirty
+     * True if this Record has been modified. Read-only.
      */
     dirty : false,
 
 <span id='Ext-data-Model-cfg-persistenceProperty'>    /**
-</span>     * @cfg {String} persistenceProperty The property on this Persistable object that its data is saved to.
-     * Defaults to 'data' (e.g. all persistable data resides in this.data.)
+</span>     * @cfg {String} persistenceProperty
+     * The property on this Persistable object that its data is saved to. Defaults to 'data'
+     * (e.g. all persistable data resides in this.data.)
      */
     persistenceProperty: 'data',
 
@@ -527,42 +591,73 @@ Ext.define('Ext.data.Model', {
     isModel: true,
 
 <span id='Ext-data-Model-property-phantom'>    /**
-</span>     * &lt;tt&gt;true&lt;/tt&gt; when the record does not yet exist in a server-side database (see
-     * {@link #setDirty}).  Any record which has a real database pk set as its id property
-     * is NOT a phantom -- it's real.
-     * @property phantom
-     * @type {Boolean}
+</span>     * @property {Boolean} phantom
+     * True when the record does not yet exist in a server-side database (see {@link #setDirty}).
+     * Any record which has a real database pk set as its id property is NOT a phantom -- it's real.
      */
     phantom : false,
 
 <span id='Ext-data-Model-cfg-idProperty'>    /**
-</span>     * @cfg {String} idProperty The name of the field treated as this Model's unique id (defaults to 'id').
+</span>     * @cfg {String} idProperty
+     * The name of the field treated as this Model's unique id. Defaults to 'id'.
      */
     idProperty: 'id',
 
-<span id='Ext-data-Model-property-defaultProxyType'>    /**
-</span>     * The string type of the default Model Proxy. Defaults to 'ajax'
-     * @property defaultProxyType
-     * @type String
+<span id='Ext-data-Model-cfg-defaultProxyType'>    /**
+</span>     * @cfg {String} defaultProxyType
+     * The string type of the default Model Proxy. Defaults to 'ajax'.
      */
     defaultProxyType: 'ajax',
 
+    // Fields config and property
+<span id='Ext-data-Model-cfg-fields'>    /**
+</span>     * @cfg {Object[]/String[]} fields
+     * The fields for this model.
+     */
 <span id='Ext-data-Model-property-fields'>    /**
-</span>     * An array of the fields defined on this model
-     * @property fields
-     * @type {Array}
+</span>     * @property {Ext.util.MixedCollection} fields
+     * The fields defined on this model.
+     */
+
+<span id='Ext-data-Model-cfg-validations'>    /**
+</span>     * @cfg {Object[]} validations
+     * An array of {@link Ext.data.validations validations} for this model.
+     */
+
+    // Associations configs and properties
+<span id='Ext-data-Model-cfg-associations'>    /**
+</span>     * @cfg {Object[]} associations
+     * An array of {@link Ext.data.Association associations} for this model.
+     */
+<span id='Ext-data-Model-cfg-hasMany'>    /**
+</span>     * @cfg {String/Object/String[]/Object[]} hasMany
+     * One or more {@link Ext.data.HasManyAssociation HasMany associations} for this model.
+     */
+<span id='Ext-data-Model-cfg-belongsTo'>    /**
+</span>     * @cfg {String/Object/String[]/Object[]} belongsTo
+     * One or more {@link Ext.data.BelongsToAssociation BelongsTo associations} for this model.
+     */
+<span id='Ext-data-Model-property-associations'>    /**
+</span>     * @property {Ext.util.MixedCollection} associations
+     * {@link Ext.data.Association Associations} defined on this model.
+     */
+
+<span id='Ext-data-Model-cfg-proxy'>    /**
+</span>     * @cfg {String/Object/Ext.data.proxy.Proxy} proxy
+     * The {@link Ext.data.proxy.Proxy proxy} to use for this model.
      */
 
     // raw not documented intentionally, meant to be used internally.
     constructor: function(data, id, raw) {
         data = data || {};
-        
+
         var me = this,
             fields,
             length,
             field,
             name,
             i,
+            newId,
             isArray = Ext.isArray(data),
             newData = isArray ? {} : null; // to hold mapped array data if needed
 
@@ -573,22 +668,18 @@ Ext.define('Ext.data.Model', {
          * @private
          */
         me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
-        
+
 <span id='Ext-data-Model-property-raw'>        /**
-</span>         * The raw data used to create this model if created via a reader.
-         * @property raw
-         * @type Object
+</span>         * @property {Object} raw The raw data used to create this model if created via a reader.
          */
         me.raw = raw;
 
         Ext.applyIf(me, {
-            data: {}    
+            data: {}
         });
-        
+
 <span id='Ext-data-Model-property-modified'>        /**
-</span>         * Key: value pairs of all fields whose values have changed
-         * @property modified
-         * @type Object
+</span>         * @property {Object} modified Key: value pairs of all fields whose values have changed
          */
         me.modified = {};
 
@@ -613,7 +704,7 @@ Ext.define('Ext.data.Model', {
             field = fields[i];
             name  = field.name;
 
-            if (isArray){ 
+            if (isArray){
                 // Have to map array data so the values get assigned to the named fields
                 // rather than getting set as the field names with undefined values.
                 newData[name] = data[i];
@@ -624,50 +715,58 @@ Ext.define('Ext.data.Model', {
         }
 
         me.set(newData || data);
-        // clear any dirty/modified since we're initializing
-        me.dirty = false;
-        me.modified = {};
 
         if (me.getId()) {
             me.phantom = false;
+        } else if (me.phantom) {
+            newId = me.idgen.generate();
+            if (newId !== null) {
+                me.setId(newId);
+            }
         }
 
+        // clear any dirty/modified since we're initializing
+        me.dirty = false;
+        me.modified = {};
+
         if (typeof me.init == 'function') {
             me.init();
         }
 
-        me.id = me.modelName + '-' + me.internalId;
+        me.id = me.idgen.getRecId(me);
     },
-    
+
 <span id='Ext-data-Model-method-get'>    /**
 </span>     * Returns the value of the given field
      * @param {String} fieldName The field to fetch the value for
-     * @return {Mixed} The value
+     * @return {Object} The value
      */
     get: function(field) {
         return this[this.persistenceProperty][field];
     },
-    
+
 <span id='Ext-data-Model-method-set'>    /**
 </span>     * Sets the given field to the given value, marks the instance as dirty
-     * @param {String|Object} fieldName The field to set, or an object containing key/value pairs
-     * @param {Mixed} value The value to set
+     * @param {String/Object} fieldName The field to set, or an object containing key/value pairs
+     * @param {Object} value The value to set
      */
     set: function(fieldName, value) {
         var me = this,
             fields = me.fields,
             modified = me.modified,
             convertFields = [],
-            field, key, i, currentValue;
+            field, key, i, currentValue, notEditing, count, length;
 
         /*
          * If we're passed an object, iterate over that object. NOTE: we pull out fields with a convert function and
          * set those last so that all other possible data is set before the convert function is called
          */
         if (arguments.length == 1 &amp;&amp; Ext.isObject(fieldName)) {
+            notEditing = !me.editing;
+            count = 0;
             for (key in fieldName) {
                 if (fieldName.hasOwnProperty(key)) {
-                
+
                     //here we check for the custom convert function. Note that if a field doesn't have a convert function,
                     //we default it to its type's convert function, so we have to check that here. This feels rather dirty.
                     field = fields.get(key);
@@ -675,16 +774,30 @@ Ext.define('Ext.data.Model', {
                         convertFields.push(key);
                         continue;
                     }
-                    
+
+                    if (!count &amp;&amp; notEditing) {
+                        me.beginEdit();
+                    }
+                    ++count;
                     me.set(key, fieldName[key]);
                 }
             }
 
-            for (i = 0; i &lt; convertFields.length; i++) {
-                field = convertFields[i];
-                me.set(field, fieldName[field]);
+            length = convertFields.length;
+            if (length) {
+                if (!count &amp;&amp; notEditing) {
+                    me.beginEdit();
+                }
+                count += length;
+                for (i = 0; i &lt; length; i++) {
+                    field = convertFields[i];
+                    me.set(field, fieldName[field]);
+                }
             }
 
+            if (notEditing &amp;&amp; count) {
+                me.endEdit();
+            }
         } else {
             if (fields) {
                 field = fields.get(fieldName);
@@ -695,7 +808,7 @@ Ext.define('Ext.data.Model', {
             }
             currentValue = me.get(fieldName);
             me[me.persistenceProperty][fieldName] = value;
-            
+
             if (field &amp;&amp; field.persist &amp;&amp; !me.isEqual(currentValue, value)) {
                 if (me.isModified(fieldName)) {
                     if (me.isEqual(modified[fieldName], value)) {
@@ -723,7 +836,7 @@ Ext.define('Ext.data.Model', {
             }
         }
     },
-    
+
 <span id='Ext-data-Model-method-isEqual'>    /**
 </span>     * Checks if two values are equal, taking into account certain
      * special factors, for example dates.
@@ -738,11 +851,10 @@ Ext.define('Ext.data.Model', {
         }
         return a === b;
     },
-    
+
 <span id='Ext-data-Model-method-beginEdit'>    /**
-</span>     * Begin an edit. While in edit mode, no events (e.g.. the &lt;code&gt;update&lt;/code&gt; event)
-     * are relayed to the containing store. When an edit has begun, it must be followed
-     * by either {@link #endEdit} or {@link #cancelEdit}.
+</span>     * Begins an edit. While in edit mode, no events (e.g.. the `update` event) are relayed to the containing store.
+     * When an edit has begun, it must be followed by either {@link #endEdit} or {@link #cancelEdit}.
      */
     beginEdit : function(){
         var me = this;
@@ -753,7 +865,7 @@ Ext.define('Ext.data.Model', {
             me.modifiedSave = Ext.apply({}, me.modified);
         }
     },
-    
+
 <span id='Ext-data-Model-method-cancelEdit'>    /**
 </span>     * Cancels all changes made in the current edit operation.
      */
@@ -770,28 +882,54 @@ Ext.define('Ext.data.Model', {
             delete me.dirtySave;
         }
     },
-    
+
 <span id='Ext-data-Model-method-endEdit'>    /**
-</span>     * End an edit. If any data was modified, the containing store is notified
-     * (ie, the store's &lt;code&gt;update&lt;/code&gt; event will fire).
+</span>     * Ends an edit. If any data was modified, the containing store is notified (ie, the store's `update` event will
+     * fire).
      * @param {Boolean} silent True to not notify the store of the change
      */
     endEdit : function(silent){
-        var me = this;
+        var me = this,
+            didChange;
+            
         if (me.editing) {
             me.editing = false;
+            didChange = me.dirty || me.changedWhileEditing();
             delete me.modifiedSave;
             delete me.dataSave;
             delete me.dirtySave;
-            if (silent !== true &amp;&amp; me.dirty) {
+            if (silent !== true &amp;&amp; didChange) {
                 me.afterEdit();
             }
         }
     },
     
+<span id='Ext-data-Model-method-changedWhileEditing'>    /**
+</span>     * Checks if the underlying data has changed during an edit. This doesn't necessarily
+     * mean the record is dirty, however we still need to notify the store since it may need
+     * to update any views.
+     * @private
+     * @return {Boolean} True if the underlying data has changed during an edit.
+     */
+    changedWhileEditing: function(){
+        var me = this,
+            saved = me.dataSave,
+            data = me[me.persistenceProperty],
+            key;
+            
+        for (key in data) {
+            if (data.hasOwnProperty(key)) {
+                if (!me.isEqual(data[key], saved[key])) {
+                    return true;
+                }
+            }
+        }
+        return false; 
+    },
+
 <span id='Ext-data-Model-method-getChanges'>    /**
 </span>     * Gets a hash of only the fields that have been modified since this Model was created or commited.
-     * @return Object
+     * @return {Object}
      */
     getChanges : function(){
         var modified = this.modified,
@@ -806,30 +944,27 @@ Ext.define('Ext.data.Model', {
 
         return changes;
     },
-    
+
 <span id='Ext-data-Model-method-isModified'>    /**
-</span>     * Returns &lt;tt&gt;true&lt;/tt&gt; if the passed field name has been &lt;code&gt;{@link #modified}&lt;/code&gt;
-     * since the load or last commit.
+</span>     * Returns true if the passed field name has been `{@link #modified}` since the load or last commit.
      * @param {String} fieldName {@link Ext.data.Field#name}
      * @return {Boolean}
      */
     isModified : function(fieldName) {
         return this.modified.hasOwnProperty(fieldName);
     },
-    
+
 <span id='Ext-data-Model-method-setDirty'>    /**
-</span>     * &lt;p&gt;Marks this &lt;b&gt;Record&lt;/b&gt; as &lt;code&gt;{@link #dirty}&lt;/code&gt;.  This method
-     * is used interally when adding &lt;code&gt;{@link #phantom}&lt;/code&gt; records to a
-     * {@link Ext.data.Store#writer writer enabled store}.&lt;/p&gt;
-     * &lt;br&gt;&lt;p&gt;Marking a record &lt;code&gt;{@link #dirty}&lt;/code&gt; causes the phantom to
-     * be returned by {@link Ext.data.Store#getModifiedRecords} where it will
-     * have a create action composed for it during {@link Ext.data.Store#save store save}
-     * operations.&lt;/p&gt;
+</span>     * Marks this **Record** as `{@link #dirty}`. This method is used interally when adding `{@link #phantom}` records
+     * to a {@link Ext.data.proxy.Server#writer writer enabled store}.
+     *
+     * Marking a record `{@link #dirty}` causes the phantom to be returned by {@link Ext.data.Store#getUpdatedRecords}
+     * where it will have a create action composed for it during {@link Ext.data.Model#save model save} operations.
      */
     setDirty : function() {
         var me = this,
             name;
-        
+
         me.dirty = true;
 
         me.fields.each(function(field) {
@@ -848,15 +983,17 @@ Ext.define('Ext.data.Model', {
         return this.setDirty.apply(this, arguments);
     },
     //&lt;/debug&gt;
-    
+
 <span id='Ext-data-Model-method-reject'>    /**
-</span>     * Usually called by the {@link Ext.data.Store} to which this model instance has been {@link #join joined}.
-     * Rejects all changes made to the model instance since either creation, or the last commit operation.
-     * Modified fields are reverted to their original values.
-     * &lt;p&gt;Developers should subscribe to the {@link Ext.data.Store#update} event
-     * to have their code notified of reject operations.&lt;/p&gt;
-     * @param {Boolean} silent (optional) True to skip notification of the owning
-     * store of the change (defaults to false)
+</span>     * Usually called by the {@link Ext.data.Store} to which this model instance has been {@link #join joined}. Rejects
+     * all changes made to the model instance since either creation, or the last commit operation. Modified fields are
+     * reverted to their original values.
+     *
+     * Developers should subscribe to the {@link Ext.data.Store#update} event to have their code notified of reject
+     * operations.
+     *
+     * @param {Boolean} silent (optional) True to skip notification of the owning store of the change.
+     * Defaults to false.
      */
     reject : function(silent) {
         var me = this,
@@ -881,19 +1018,19 @@ Ext.define('Ext.data.Model', {
     },
 
 <span id='Ext-data-Model-method-commit'>    /**
-</span>     * Usually called by the {@link Ext.data.Store} which owns the model instance.
-     * Commits all changes made to the instance since either creation or the last commit operation.
-     * &lt;p&gt;Developers should subscribe to the {@link Ext.data.Store#update} event
-     * to have their code notified of commit operations.&lt;/p&gt;
-     * @param {Boolean} silent (optional) True to skip notification of the owning
-     * store of the change (defaults to false)
+</span>     * Usually called by the {@link Ext.data.Store} which owns the model instance. Commits all changes made to the
+     * instance since either creation or the last commit operation.
+     *
+     * Developers should subscribe to the {@link Ext.data.Store#update} event to have their code notified of commit
+     * operations.
+     *
+     * @param {Boolean} silent (optional) True to skip notification of the owning store of the change.
+     * Defaults to false.
      */
     commit : function(silent) {
         var me = this;
-        
-        me.dirty = false;
-        me.editing = false;
 
+        me.phantom = me.dirty = me.editing = false;
         me.modified = {};
 
         if (silent !== true) {
@@ -903,24 +1040,27 @@ Ext.define('Ext.data.Model', {
 
 <span id='Ext-data-Model-method-copy'>    /**
 </span>     * Creates a copy (clone) of this Model instance.
-     * @param {String} id (optional) A new id, defaults to the id
-     * of the instance being copied. See &lt;code&gt;{@link #id}&lt;/code&gt;.
-     * To generate a phantom instance with a new id use:&lt;pre&gt;&lt;code&gt;
-var rec = record.copy(); // clone the record
-Ext.data.Model.id(rec); // automatically generate a unique sequential id
-     * &lt;/code&gt;&lt;/pre&gt;
-     * @return {Record}
+     *
+     * @param {String} [id] A new id, defaults to the id of the instance being copied.
+     * See `{@link Ext.data.Model#id id}`. To generate a phantom instance with a new id use:
+     *
+     *     var rec = record.copy(); // clone the record
+     *     Ext.data.Model.id(rec); // automatically generate a unique sequential id
+     *
+     * @return {Ext.data.Model}
      */
     copy : function(newId) {
         var me = this;
-        
+
         return new me.self(Ext.apply({}, me[me.persistenceProperty]), newId || me.internalId);
     },
 
 <span id='Ext-data-Model-method-setProxy'>    /**
-</span>     * Sets the Proxy to use for this model. Accepts any options that can be accepted by {@link Ext#createByAlias Ext.createByAlias}
+</span>     * Sets the Proxy to use for this model. Accepts any options that can be accepted by
+     * {@link Ext#createByAlias Ext.createByAlias}.
+     *
      * @param {String/Object/Ext.data.proxy.Proxy} proxy The proxy
-     * @static
+     * @return {Ext.data.proxy.Proxy}
      */
     setProxy: function(proxy) {
         //make sure we have an Ext.data.proxy.Proxy object
@@ -939,7 +1079,7 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-getProxy'>    /**
-</span>     * Returns the configured Proxy for this Model
+</span>     * Returns the configured Proxy for this Model.
      * @return {Ext.data.proxy.Proxy} The proxy
      */
     getProxy: function() {
@@ -947,8 +1087,7 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-validate'>    /**
-</span>     * Validates the current data against all of its configured {@link #validations} and returns an
-     * {@link Ext.data.Errors Errors} object
+</span>     * Validates the current data against all of its configured {@link #validations}.
      * @return {Ext.data.Errors} The errors object
      */
     validate: function() {
@@ -987,8 +1126,8 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-save'>    /**
-</span>     * Saves the model instance using the configured proxy
-     * @param {Object} options Options to pass to the proxy
+</span>     * Saves the model instance using the configured proxy.
+     * @param {Object} options Options to pass to the proxy. Config object for {@link Ext.data.Operation}.
      * @return {Ext.data.Model} The Model instance
      */
     save: function(options) {
@@ -1030,8 +1169,8 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-destroy'>    /**
-</span>     * Destroys the model using the configured proxy
-     * @param {Object} options Options to pass to the proxy
+</span>     * Destroys the model using the configured proxy.
+     * @param {Object} options Options to pass to the proxy. Config object for {@link Ext.data.Operation}.
      * @return {Ext.data.Model} The Model instance
      */
     destroy: function(options){
@@ -1063,7 +1202,7 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-getId'>    /**
-</span>     * Returns the unique ID allocated to this model instance as defined by {@link #idProperty}
+</span>     * Returns the unique ID allocated to this model instance as defined by {@link #idProperty}.
      * @return {Number} The id
      */
     getId: function() {
@@ -1071,7 +1210,7 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-setId'>    /**
-</span>     * Sets the model instance's id field to the given id
+</span>     * Sets the model instance's id field to the given id.
      * @param {Number} id The new id
      */
     setId: function(id) {
@@ -1079,22 +1218,22 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-join'>    /**
-</span>     * Tells this model instance that it has been added to a store
-     * @param {Ext.data.Store} store The store that the model has been added to
+</span>     * Tells this model instance that it has been added to a store.
+     * @param {Ext.data.Store} store The store to which this model has been added.
      */
     join : function(store) {
 <span id='Ext-data-Model-property-store'>        /**
-</span>         * The {@link Ext.data.Store} to which this Record belongs.
-         * @property store
-         * @type {Ext.data.Store}
+</span>         * @property {Ext.data.Store} store
+         * The {@link Ext.data.Store Store} to which this Record belongs.
          */
         this.store = store;
     },
 
 <span id='Ext-data-Model-method-unjoin'>    /**
-</span>     * Tells this model instance that it has been removed from the store
+</span>     * Tells this model instance that it has been removed from the store.
+     * @param {Ext.data.Store} store The store from which this model has been removed.
      */
-    unjoin: function() {
+    unjoin: function(store) {
         delete this.store;
     },
 
@@ -1141,20 +1280,21 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
     },
 
 <span id='Ext-data-Model-method-getAssociatedData'>    /**
-</span>     * Gets all of the data from this Models *loaded* associations.
-     * It does this recursively - for example if we have a User which
-     * hasMany Orders, and each Order hasMany OrderItems, it will return an object like this:
-     * {
-     *     orders: [
-     *         {
-     *             id: 123,
-     *             status: 'shipped',
-     *             orderItems: [
-     *                 ...
-     *             ]
-     *         }
-     *     ]
-     * }
+</span>     * Gets all of the data from this Models *loaded* associations. It does this recursively - for example if we have a
+     * User which hasMany Orders, and each Order hasMany OrderItems, it will return an object like this:
+     *
+     *     {
+     *         orders: [
+     *             {
+     *                 id: 123,
+     *                 status: 'shipped',
+     *                 orderItems: [
+     *                     ...
+     *                 ]
+     *             }
+     *         ]
+     *     }
+     *
      * @return {Object} The nested data set for the Model's loaded associations
      */
     getAssociatedData: function(){
@@ -1166,7 +1306,7 @@ Ext.data.Model.id(rec); // automatically generate a unique sequential id
      * This complex-looking method takes a given Model instance and returns an object containing all data from
      * all of that Model's *loaded* associations. See (@link #getAssociatedData}
      * @param {Ext.data.Model} record The Model instance
-     * @param {Array} ids PRIVATE. The set of Model instance internalIds that have already been loaded
+     * @param {String[]} ids PRIVATE. The set of Model instance internalIds that have already been loaded
      * @param {String} associationType (optional) The name of the type of association to limit to.
      * @return {Object} The nested data set for the Model's loaded associations
      */