diff --git a/lib/model.js b/lib/model.js index 888d437..eaf64b9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -71,6 +71,12 @@ CKAN.Model = function ($, _, Backbone, undefined) { // Model objects Model.Dataset = Model.Base.extend({ constructor: function Dataset() { + // Define an key/model mapping for child relationships. These will be + // managed as a Backbone collection when setting/getting the key. + this.children = { + resources: Model.Resource, + relationships: Model.Relationship + }; Model.Base.prototype.constructor.apply(this, arguments); }, @@ -81,12 +87,9 @@ CKAN.Model = function ($, _, Backbone, undefined) { set: function (attributes, options) { var resources, validated; - // If not yet defined set the resources collection. This will be done when + // If not yet defined set the child collections. This will be done when // set is called for the first time in the constructor. - if (!this.get('resources')) { - this.attributes.resources = new Backbone.Collection(); - this.attributes.resources.model = Model.Resource; - } + this._createRelationships(); if (attributes && attributes.resources) { if (!(attributes.resources instanceof Backbone.Collection)) { @@ -105,6 +108,18 @@ CKAN.Model = function ($, _, Backbone, undefined) { return validated; }, + // Checks to see if our model instance has Backbone collections defined for + // child keys. If they do not exist it creates them. + _createRelationships: function () { + _.each(this.children, function (Model, key) { + if (!this.get(key)) { + this.attributes[key] = new Backbone.Collection(); + this.attributes[key].model = Model; + } + }, this); + return this; + }, + // Manages the one to many relationship between resources and the dataset. // Accepts an array of Resources (ideally model instances but will convert // object literals into resources for you). New models will be added to the diff --git a/test/model-test.js b/test/model-test.js index a9e4f43..3adf282 100644 --- a/test/model-test.js +++ b/test/model-test.js @@ -73,13 +73,13 @@ test(".set({resources: []})", function () { resources = dataset.get('resources'), newResources = new Backbone.Collection(); + this.spy(dataset, '_createRelationships'); this.spy(dataset, '_updateResources'); - equals(resources.constructor, Backbone.Collection, 'The resources attribute should be a Backbone collection'); - equals(resources.model, CKAN.Model.Resource, 'Should create Resource instances'); equals(resources.length, 0, 'The resources collection should be empty'); dataset.set({}); + equals(dataset._createRelationships.callCount, 1, 'Expected dataset._createRelationships() to have been called'); ok(!dataset._updateResources.calledOnce, 'Expected collection._updateResources() NOT to have been called'); dataset.set({resources: newResources}); @@ -93,6 +93,20 @@ test(".set({resources: []})", function () { ok(dataset._updateResources.calledTwice, 'Expected collection._updateResources() to have been called'); }); +test("._createRelationships()", function () { + var dataset = new CKAN.Model.Dataset(), attrs, returned; + attrs = dataset.attributes = {}; + + returned = dataset._createRelationships(); + + ok(dataset, returned, 'Expected it to return itself'); + equals(attrs.resources.constructor, Backbone.Collection, 'The resources attribute should be a Backbone collection'); + equals(attrs.resources.model, CKAN.Model.Resource, 'Should create Resource instances'); + + equals(attrs.relationships.constructor, Backbone.Collection, 'The resources attribute should be a Backbone collection'); + equals(attrs.relationships.model, CKAN.Model.Relationship, 'Should create Resource instances'); +}); + test("._updateResources()", function () { var dataset = new CKAN.Model.Dataset(), resources = dataset.get('resources'),