vendor/assets/javascripts/railsy_backbone.sync.js

NOTE: only overriding Backbone when railsy_backbone (start) ... (end) is explicitly called out.

Overriding Backbone.sync to implement,
- Nested model attributes
- Rails CSFR Integration

( function($){

Define methodMap since it's called from within Backbone.sync

var methodMap = { 'create': 'POST', 'update': 'PUT', 'patch': 'PATCH', 'delete': 'DELETE', 'read': 'GET' }; var urlError = function() { throw new Error("A 'url' property or function must be specified"); }; Backbone.sync = function(method, model, options) { var type = methodMap[method];

Default options, unless specified.

_.defaults(options || (options = {}), { emulateHTTP: Backbone.emulateHTTP, emulateJSON: Backbone.emulateJSON });

Default JSON-request options.

var params = {type: type, dataType: 'json'};

Ensure that we have a URL.

if (!options.url) { params.url = _.result(model, 'url') || urlError(); }

railsy_backbone (start)
Rails CSFR Integration

include the Rails CSRF token on HTTP PUTs/POSTs

if(!options.noCSRF){ var beforeSend = options.beforeSend;

Set X-CSRF-Token HTTP header

options.beforeSend = function(xhr) { var token = $('meta[name="csrf-token"]').attr('content'); if (token) xhr.setRequestHeader('X-CSRF-Token', token); if (beforeSend) return beforeSend.apply(this, arguments); }; }

railsy_backbone (end)


Ensure that we have the appropriate request data.

if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { params.contentType = 'application/json';

railsy_backbone (start)
Nested Model Attributes

If Backbone.Model defines paramRoot, then store model attributes within paramRoot key-value pair. For example, book attributes (title, author) are nested within book key-value pair,

 var Book = Backbone.Model.extend({ 
   url: '/books',
   paramRoot: 'book' 
 });

 var book_instance = new Book({ 
   title:  'the illiad', 
   author: 'homer'
 });

The resulting HTTP POST looks like this,

 book_instance.sync();

 Started POST "/books" for 127.0.0.1
   Processing by BooksController#create as JSON
   { "book" => { "title" => "the illiad", "author" => "home", "id" => 1} }
if(model.paramRoot) { var model_attributes = {}

Store model instance in JSON format.

var attrs = model.toJSON(options);

Remove Rails unofficially reserved created_at and updated_at so they're included in HTTP PUT/PATCH request.

delete attrs["created_at"]; delete attrs["updated_at"];

Nest model attributes within model's paramRoot key-value pair.

model_attributes[model.paramRoot] = attrs; params.data = JSON.stringify(options.attrs || model_attributes); } else {

If model does not define a paramRoot, use the original Backbone implementation.

params.data = JSON.stringify(options.attrs || model.toJSON(options) ); }

railsy_backbone (end)


}

For older servers, emulate JSON by encoding the request into an HTML-form.

if (options.emulateJSON) { params.contentType = 'application/x-www-form-urlencoded'; params.data = params.data ? {model: params.data} : {}; }

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.data._method = type; var beforeSend = options.beforeSend; options.beforeSend = function(xhr) { xhr.setRequestHeader('X-HTTP-Method-Override', type); if (beforeSend) return beforeSend.apply(this, arguments); }; }

Don't process data on a non-GET request.

if (params.type !== 'GET' && !options.emulateJSON) { params.processData = false; }

If we're sending a PATCH request, and we're in an old Internet Explorer that still has ActiveX enabled by default, override jQuery to use that for XHR instead. Remove this line when jQuery supports PATCH on IE8.

if (params.type === 'PATCH' && window.ActiveXObject && !(window.external && window.external.msActiveXFilteringEnabled)) { params.xhr = function() { return new ActiveXObject("Microsoft.XMLHTTP"); }; }

Make the request, allowing the user to override any Ajax options.

var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); model.trigger('request', model, xhr, options); return xhr; }; })(jQuery);