Forked from efeminella/backbone-persistable-collection.js
Created
October 29, 2012 20:22
-
-
Save hansede/3976291 to your computer and use it in GitHub Desktop.
A Persistable Backbone Collection Implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Copyright (c) 2012 Eric Feminella, http://code.ericfeminella.com/license/LICENSE.txt | |
*/ | |
( function( _, Backbone ) | |
{ | |
// convenience reference to the Backbone.Collection constructor | |
var _initialize = Backbone.Collection.prototype.initialize; | |
/* | |
* The Backbone.PersistableCollection provides a simply abstraction which | |
* extends the Backbone Collection API in order to allow a collection to | |
* be persisted in a similar manner to that which is implemented by the | |
* Backbone.Model via the save method. | |
* | |
* Note: The Backbone.PersistableCollection is a simple abstraction in that | |
* the underlying implementation simply saves a complete representation of | |
* the collection and it's models when sent to the server. | |
* | |
*/ | |
Backbone.PersistableCollection = Backbone.Collection.extend( | |
{ | |
/* | |
* Provides an override of Backbone.Collection.initialize which, when | |
* a new Backbone.PersistableCollection is instantiated, will create | |
* the proxy for this collection, invoking the super constructor with | |
* any defaults provided. | |
* | |
*/ | |
initialize: function( models, options ) | |
{ | |
_initialize.call( this, models, options ); | |
this.proxy = Backbone.PersistableCollection.createProxy( this ); | |
}, | |
/* | |
* Saves the collection as a representation of all models based on the | |
* state of the collection. | |
*/ | |
save: function( options ) | |
{ | |
return this.proxy.save( '', null, options ); | |
} | |
}, | |
{ | |
/* | |
* Provides a static factory method which, given a collection, creates | |
* a proxy which wraps the collection in a Backbone.Model, thus allowing | |
* the collection to be saved in the same manner as one would typically | |
* persist a Backbone.Model. | |
* | |
* The createProxy method will only create a single proxy per collection. | |
* Therefore, if createProxy is called with the same collection more than | |
* once, the existing proxy will be returned. If createProxy is invoked | |
* with a collection being provided, an exception is thrown. | |
* | |
* <pre> | |
* | |
* var users = new Backbone.Collection([ | |
* { name: "Joe", id: 5}, | |
* { name: "Bob", id: 26} | |
* ]); | |
* users.url = '/users'; | |
* | |
* var proxy = Backbone.PersistableCollection.createProxy( users ); | |
* proxy.save(); // saves the collection to /users | |
* | |
* </pre> | |
* | |
*/ | |
createProxy: function( collection ) | |
{ | |
if ( collection ) | |
{ | |
if ( !collection.proxy ) | |
{ | |
collection.proxy = _.extend( new Backbone.Model(), | |
{ | |
url: collection.url, | |
toJSON: function() | |
{ | |
return collection.toJSON(); | |
} | |
}); | |
} | |
return collection.proxy; | |
} | |
throw new Error( 'A collection must be provided to implement the proxy' ); | |
} | |
}); | |
}( _, Backbone )); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Copyright (c) 2012 Eric Feminella, http://code.ericfeminella.com/license/LICENSE.txt | |
*/ | |
(function(a,b){var c=b.Collection.prototype.initialize;b.PersistableCollection=b.Collection.extend({initialize:function(a,d){c.call(this,a,d),this.proxy=b.PersistableCollection.createProxy(this)},save:function(a){return this.proxy.save('',null,a)}},{createProxy:function(c){if(c)return c.proxy||(c.proxy=a.extend(new b.Model,{url:c.url,toJSON:function(){return c.toJSON()}})),c.proxy;throw new Error("A collection must be provided to implement the proxy")}})})(_,Backbone) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* Copyright (c) 2012 Eric Feminella, http://code.ericfeminella.com/license/LICENSE.txt | |
*/ | |
describe( "The Backbone.PersistableCollection", function() | |
{ | |
it( "should extend Backbone.Collection", function() | |
{ | |
expect( new Backbone.PersistableCollection() instanceof Backbone.Collection ).toBeTruthy(); | |
}); | |
describe( "The createProxy method", function() | |
{ | |
beforeEach( function() | |
{ | |
this.collection = new Backbone.Collection([ | |
{ name: "Joe", id: 5}, | |
{ name: "Bob", id: 26} | |
]); | |
this.collection.url = "/users"; | |
}); | |
it( "should only create one unique proxy per collection ", function() | |
{ | |
var proxy = Backbone.PersistableCollection.createProxy( this.collection ); | |
expect( Backbone.PersistableCollection.createProxy( this.collection ) ).toEqual( proxy ); | |
}); | |
it( "should throw an exception if a collection is not specified", function() | |
{ | |
expect( function(){ | |
Backbone.PersistableCollection.createProxy() | |
}).toThrow(); | |
}); | |
it( "should be assigned the collection's url value", function() | |
{ | |
expect( Backbone.PersistableCollection.createProxy( this.collection ).url ).toEqual( this.collection.url ); | |
}); | |
it( "should reference the collection's url function", function() | |
{ | |
var expected, actual; | |
this.collection = new Backbone.Collection(); | |
this.collection.url = function(){ | |
return '/some/path/users'; | |
}; | |
expected = Backbone.PersistableCollection.createProxy( this.collection ).url; | |
actual = this.collection.url; | |
expect( expected ).toEqual( actual ); | |
expect( expected() ).toEqual( actual() ); | |
}); | |
it( "should return the collection's toJSON value when toJSON is called", function() | |
{ | |
expect( Backbone.PersistableCollection.createProxy( this.collection ).toJSON() ).toEqual( this.collection.toJSON() ); | |
}); | |
}); | |
describe( "The save method", function() | |
{ | |
describe( "When saving a PersistableCollection instance", function() | |
{ | |
beforeEach( function() | |
{ | |
this.collection = new Backbone.PersistableCollection([ | |
{ name: "Joe", id: 5}, | |
{ name: "Bob", id: 26} | |
]); | |
this.collection.url = "/users"; | |
}); | |
it( "should invoke save on the underlying proxy", function() | |
{ | |
spyOn( this.collection.proxy, 'save' ); | |
spyOn( $, 'ajax' ).andCallFake( function( options ){}); | |
this.collection.save(); | |
expect( this.collection.proxy.save).toHaveBeenCalled(); | |
}); | |
it( "should invoke save on the underlying proxy with the specified options", function() | |
{ | |
var options = {}; | |
spyOn( this.collection.proxy, 'save' ); | |
spyOn( $, 'ajax' ).andCallFake( function( options ){}); | |
this.collection.save( options ); | |
expect( this.collection.proxy.save).toHaveBeenCalledWith( options ); | |
}); | |
}); | |
describe( "When saving a Backbone.Collection instance", function() | |
{ | |
beforeEach( function() | |
{ | |
this.collection = new Backbone.Collection([ | |
{ name: "Joe", id: 5}, | |
{ name: "Bob", id: 26} | |
]); | |
this.collection.url = "/users"; | |
this.proxy = Backbone.PersistableCollection.createProxy( this.collection ); | |
}); | |
it( "should invoke save on the underlying proxy", function() | |
{ | |
spyOn( this.proxy, 'save' ); | |
spyOn( $, 'ajax' ).andCallFake( function( options ){}); | |
this.proxy.save(); | |
expect( this.proxy.save).toHaveBeenCalled(); | |
}); | |
it( "should invoke save on the underlying proxy with the specified options", function() | |
{ | |
var options = {}; | |
spyOn( this.proxy, 'save' ); | |
spyOn( $, 'ajax' ).andCallFake( function( options ){}); | |
this.proxy.save( options ); | |
expect( this.proxy.save).toHaveBeenCalledWith( options ); | |
}); | |
}); | |
describe( "When the Collection is null", function() | |
{ | |
beforeEach( function() | |
{ | |
this.collection = new Backbone.Collection([ | |
{ name: "Joe", id: 5}, | |
{ name: "Bob", id: 26} | |
]); | |
this.collection.url = "/users"; | |
this.proxy = Backbone.PersistableCollection.createProxy( this.collection ); | |
}); | |
it( "should throw an exception", function() | |
{ | |
this.collection = null; | |
expect( function(){ | |
this.proxy.save(); | |
}).toThrow(); | |
}); | |
}); | |
}); | |
describe( "toJSON", function() | |
{ | |
beforeEach( function() | |
{ | |
var UsersCollection = Backbone.PersistableCollection.extend({ | |
url: "/users" | |
}); | |
this.collection = new UsersCollection([ | |
{ name: "Joe", id: 5}, | |
{ name: "Bob", id: 26} | |
]); | |
}); | |
it( "should invoke toJSON on the underlying collection via the proxy", function() | |
{ | |
spyOn( this.collection, 'toJSON' ); | |
spyOn( $, 'ajax' ).andCallFake( function( options ){}); | |
this.collection.save(); | |
expect( this.collection.toJSON ).toHaveBeenCalled(); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment