docs: function(base, fullName, staticProps, protoProps) {
                      // Assume `fullName` wasn't passed. (`can.Model.extend({ ... }, { ... })`)
                      // This is pretty usual.
                      if (fullName !== "string") {
                          protoProps = staticProps;
                          staticProps = fullName;
                      }
                      // Assume no static properties were passed. (`can.Model.extend({ ... })`)
                      // This is really unusual for a model though, since there's so much configuration.
                      if (!protoProps) {
                          protoProps = staticProps;
                      }
  
                      // Create the model store here, in case someone wants to use can.Model without inheriting from it.
                      this.store = {};
  
                      can.Map.setup.apply(this, arguments);
                      if (!can.Model) {
                          return;
                      }
  
                      // `List` is just a regular can.Model.List that knows what kind of Model it's hooked up to.
  
                      if (staticProps && staticProps.List) {
                          this.List = staticProps.List;
                          this.List.Map = this;
                      } else {
                          this.List = base.List.extend({
                                  Map: this
                              }, {});
                      }
  
                      var self = this,
                          clean = can.proxy(this._clean, self);
  
                      // Go through `ajaxMethods` and set up static methods according to their configurations.
                      can.each(ajaxMethods, function(method, name) {
                          // Check the configuration for this ajaxMethod.
                          // If the configuration isn't a function, it should be a string (like `"GET /endpoint"`)
                          // or an object like `{url: "/endpoint", type: 'GET'}`.
                          if (!can.isFunction(self[name])) {
                              // Etiher way, `ajaxMaker` will turn it into a function for us.
                              self[name] = ajaxMaker(method, self[name] ? self[name] : createURLFromResource(self, name));
                          }
  
                          // There may also be a "maker" function (like `makeFindAll`) that alters the behavior of acting upon models
                          // by changing when and how the function we just made with `ajaxMaker` gets called.
                          // For example, you might cache responses and only make a call when you don't have a cached response.
                          if (self["make" + can.capitalize(name)]) {
                              // Use the "maker" function to make the new "ajaxMethod" function.
                              var newMethod = self["make" + can.capitalize(name)](self[name]);
                              // Replace the "ajaxMethod" function in the configuration with the new one.
                              // (`_overwrite` just overwrites a property in a given Construct.)
                              can.Construct._overwrite(self, base, name, function() {
                                  // Increment the numer of requests...
                                  can.Model._reqs++;
                                  // ...make the AJAX call (and whatever else you're doing)...
                                  var def = newMethod.apply(this, arguments);
                                  // ...and clean up the store.
                                  var then = def.then(clean, clean);
                                  // Pass along `abort` so you can still abort the AJAX call.
                                  then.abort = def.abort;
  
                                  return then;
                              });
                          }
                      });
  
                      // Set up the methods that will set up `models` and `model`.
                      can.each(initializers, function(makeInitializer, name) {
                          var parseName = "parse" + can.capitalize(name),
                              dataProperty = self[name];
  
                          // If there was a different property to find the model's data in than `data`,
                          // make `parseModel` and `parseModels` functions that look that up instead.
                          if (typeof dataProperty === "string") {
                              can.Construct._overwrite(self, base, parseName, parsers[parseName](dataProperty));
                              can.Construct._overwrite(self, base, name, makeInitializer(dataProperty));
                          }
  
                          // If there was no prototype, or no `model` and no `parseModel`,
                          // we'll have to create a `parseModel`.
                          else if (!protoProps || (!protoProps[name] && !protoProps[parseName])) {
                              can.Construct._overwrite(self, base, parseName, parsers[parseName]());
                          }
                      });
  
                      // With the overridden parse methods, set up `models` and `model`.
                      can.each(parsers, function(makeParser, name) {
                          // If there was a different property to find the model's data in than `data`,
                          // make `model` and `models` functions that look that up instead.
                          if (typeof self[name] === "string") {
                              can.Construct._overwrite(self, base, name, makeParser(self[name]));
                          }
                      });
  
                      // Make sure we have a unique name for this Model.
                      if (self.fullName === "can.Model" || !self.fullName) {
                          self.fullName = "Model" + (++modelNum);
                      }
  
                      can.Model._reqs = 0;
                      this._url = this._shortName + "/{" + this.id + "}";
                  }