/*$AMPERSAND_VERSION*/
var result = require('lodash.result');
var defaults = require('lodash.defaults');
var includes = require('lodash.includes');
var assign = require('lodash.assign');
var qs = require('qs');


module.exports = function (xhr) {

  // Throw an error when a URL is needed, and none is supplied.
  var urlError = function () {
      throw new Error('A "url" property or function must be specified');
  };

  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
  var methodMap = {
      'create': 'POST',
      'update': 'PUT',
      'patch':  'PATCH',
      'delete': 'DELETE',
      'read':   'GET'
  };

  return function (method, model, options) {
      var type = methodMap[method];
      var headers = {};

      // Default options, unless specified.
      defaults(options || (options = {}), {
          emulateHTTP: false,
          emulateJSON: false,
          // overrideable primarily to enable testing
          xhrImplementation: xhr
      });

      // Default request options.
      var params = {type: type};

      // Ensure that we have a URL.
      if (!options.url) {
          options.url = result(model, 'url') || urlError();
      }

      // Ensure that we have the appropriate request data.
      if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
          params.json = options.attrs || model.toJSON(options);
      }

      // If passed a data param, we add it to the URL or body depending on request type
      if (options.data && type === 'GET') {
          // make sure we've got a '?'
          options.url += includes(options.url, '?') ? '&' : '?';
          options.url += qs.stringify(options.data);
      }

      // For older servers, emulate JSON by encoding the request into an HTML-form.
      if (options.emulateJSON) {
          headers['content-type'] = 'application/x-www-form-urlencoded';
          params.body = params.json ? {model: params.json} : {};
          delete params.json;
      }

      // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
      // And an `X-HTTP-Method-Override` header.
      if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
          params.type = 'POST';
          if (options.emulateJSON) params.body._method = type;
          headers['x-http-method-override'] = type;
      }

      // When emulating JSON, we turn the body into a querystring.
      // We do this later to let the emulateHTTP run its course.
      if (options.emulateJSON) {
          params.body = qs.stringify(params.body);
      }

      // Start setting ajaxConfig options (headers, xhrFields).
      var ajaxConfig = (result(model, 'ajaxConfig') || {});

      // Combine generated headers with user's headers.
      if (ajaxConfig.headers) {
          for (var key in ajaxConfig.headers) {
              headers[key.toLowerCase()] = ajaxConfig.headers[key];
          }
      }
      
      params.headers = headers;

      //Set XDR for cross domain in IE8/9
      if (ajaxConfig.useXDR ) {
          params.useXDR = true;
      }

      // Set raw xhr options.
      if (ajaxConfig.xhrFields) {
          var beforeSend = ajaxConfig.beforeSend;
          params.beforeSend = function (req) {
              assign(req, ajaxConfig.xhrFields);
              if (beforeSend) return beforeSend.apply(this, arguments);
          };
          params.xhrFields = ajaxConfig.xhrFields;
      } else {
          params.beforeSend = ajaxConfig.beforeSend;
      }

      // Turn a jQuery.ajax formatted request into xhr compatible
      params.method = params.type;

      var ajaxSettings = assign(params, options);

      // Make the request. The callback executes functions that are compatible
      // With jQuery.ajax's syntax.
      var request = options.xhr = options.xhrImplementation(ajaxSettings, function (err, resp, body) {
          if (err || resp.statusCode >= 400) {
              if (options.error) {
                  var message = (err? err.message : (body || "HTTP"+resp.statusCode));
                  options.error(resp, 'error', message);
              }
          } else {
              // Parse body as JSON
              if (typeof body === 'string' && (!headers.accept || headers.accept.indexOf('application/json')===0)) {
                  try {
                      body = JSON.parse(body);
                  } catch (err) {
                      if (options.error) options.error(resp, 'error', err.message);
                      if (options.always) options.always(err, resp, body);
                      return;
                  }
              }
              if (options.success) options.success(body, 'success', resp);
          }
          if (options.always) options.always(err, resp, body);
      });
      model.trigger('request', model, request, options, ajaxSettings);
      request.ajaxSettings = ajaxSettings;
      return request;
  };
};

@@ -4840,16 +4840,27 @@
 );%0A     
+ if (model)
  model.t

Make model optional