diff --git a/model/model.js b/model/model.js index 24ef9683..f3f5125c 100644 --- a/model/model.js +++ b/model/model.js @@ -404,6 +404,18 @@ steal.plugins('jquery/class', 'jquery/lang').then(function() { * @codeend */ defaults: {}, + /** + * WrapWith is used to decide wrap class for object. + * It is a convience method to avoid unnecessary overwriting + * Wrap method. It enables simpler implementation of system + * similar to Rails STI (single table inheritance). + * + * @param {Object} attributes + * @return {Class} a class that will wrap the object + */ + wrapWith: function( attributes ) { + return this; + }, /** * Wrap is used to create a new instance from data returned from the server. * It is very similar to doing new Model(attributes) @@ -424,9 +436,11 @@ steal.plugins('jquery/class', 'jquery/lang').then(function() { if (!attributes ) { return null; } - return new this( // checks for properties in an object (like rails 2.0 gives); - attributes[this.singularName] || attributes.data || attributes.attributes || attributes); + var attrs = attributes[this.singularName] || attributes.data || attributes.attributes || attributes; + // grab the wrapper class and wrap the attributes + var wrapper = this.wrapWith(attrs); + return new wrapper(attrs); }, /** * Takes raw data from the server, and returns an array of model instances. diff --git a/model/test/qunit/model_test.js b/model/test/qunit/model_test.js index 0eb3880b..353f349c 100644 --- a/model/test/qunit/model_test.js +++ b/model/test/qunit/model_test.js @@ -22,6 +22,31 @@ module("jquery/model", { return "Mr. "+this.name; } }) + + $.Model.extend("Animal",{ + wrapWith: function( attrs ) { + if(attrs.animal_type == 'dog') return Dog; + if(attrs.animal_type == 'cat') return Cat; + return this; + } + },{ + animal: function() { + return 'animal'; + } + }); + + Animal.extend("Dog",{},{ + animal: function() { + return 'dog'; + } + }); + Animal.extend("Cat",{},{ + animal: function() { + return 'cat'; + } + }); + + } }) @@ -141,3 +166,12 @@ test("isNew", function(){ var p3 = new Person({id: 0}) ok(!p3.isNew(), "0 is not new"); }) + +test("wrapWith", function(){ + var dog = Animal.wrap({animal_type: 'dog', name: 'Rex'}); + var cat = Animal.wrap({animal_type: 'cat', name: 'Garfield'}); + var mouse = Animal.wrap({animal_type: 'mouse', name: 'Jerry'}); + equals(dog.animal(), 'dog', 'call correct animal method from dog subclass'); + equals(cat.animal(), 'cat', 'call correct animal method from cat subclass'); + equals(mouse.animal(), 'animal', 'call correct animal method from base Animal class'); +})