Last active
August 29, 2015 14:05
-
-
Save ivanseidel/cf2bf4d3ef405e90122f to your computer and use it in GitHub Desktop.
GeddyJs belongsToMany with Array helper
This file contains 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
/* | |
* GeddyJs belongsToMany helper module | |
* Ivan Seidel Gomes ([email protected]) | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
Creates a geddy association between thisModel and thatModel. | |
Examples (inside model declaration): | |
belongsToMany(this, 'Photos'); | |
With options: | |
// User model | |
belongsToMany(this, 'Users', { | |
as: 'Friendships', | |
otherKey: 'facebookId', | |
}); | |
// Photo model | |
belongsToMany(this, 'Users'); | |
// Coach | |
belongsToMany(this, 'Teams', { | |
as: 'CoachedTeams' | |
}); | |
*/ | |
var _ = require('lodash'); | |
var inflection = geddy.inflection; | |
var belongsToMany = function (model, thatModel, opts) { | |
opts = _.defaults(opts || {}, { | |
as: thatModel, | |
otherKey: 'id', | |
}); | |
// Other Model name | |
var thatModelName = inflection.singularize(thatModel); | |
// Key used in this model to store ids | |
var thisNameSingular = inflection.singularize(opts.as); | |
var thisNamePlural = inflection.pluralize(opts.as); | |
// Key used in this model to save array | |
var thisKeyName = thisNameSingular.toLowerCase() + 'Ids'; | |
// Setup property | |
model.property(thisKeyName, 'object'); | |
// Extract ids from model list | |
function pluckSmart(models, key){ | |
var modelIds = []; | |
for(var k in models){ | |
var checkModel = models[k]; | |
// If is an object, extract the id from it | |
if(!checkModel){ | |
// Skip. It's empty/null/0 | |
}else if(_.isObject(checkModel)){ | |
// Id is stored in `otherKey` field | |
modelIds.push(checkModel[key]); | |
}else{ | |
// Push it. Should be the id... | |
modelIds.push(checkModel); | |
} | |
} | |
return modelIds; | |
} | |
// Get model method name (this side) | |
var getModels = 'get'+thisNamePlural; | |
model[getModels] = function (next){ | |
var modelIds = this[thisKeyName] || []; | |
// If next is assigned, we associate and fetch models | |
if(_.isFunction(next)){ | |
if(!modelIds){ | |
// Nothing. Just callback | |
next(null, []); | |
}else{ | |
// Find Model and create Query | |
var otherModel = geddy.model[thatModelName]; | |
if(!otherModel) throw new Error('Model '+thatModelName+' not found'); | |
var query = {}; | |
query[opts.otherKey] = modelIds; | |
// Query it | |
otherModel.all(query, next); | |
} | |
} | |
// Returns data (already loaded in model) | |
return modelIds; | |
}; | |
var removeModels = 'remove'+thisNamePlural; | |
model[removeModels] = function (models){ | |
if(!models) models = []; | |
if(!_.isArray(models)) models = [models]; | |
// Get Current ids in this model property | |
var modelIds = pluckSmart(models, opts.otherKey); | |
// Now we have a list of ids. Let's find and remove it: | |
var newIds = _.difference(this[thisKeyName], modelIds); | |
// Set to model | |
var newProps = {}; | |
newProps[thisKeyName] = newIds; | |
this.updateProperties(modelIds); | |
// Return filteded Ids | |
return newIds; | |
}; | |
var addModel = 'add'+thisNameSingular; | |
var addModels = 'add'+thisNamePlural; | |
model[addModel] = model[addModels] = function (models){ | |
if(!models) models = []; | |
if(!_.isArray(models)) models = [models]; | |
// Get Current ids in this model property | |
var modelIds = pluckSmart(models, opts.otherKey); | |
// Now we have a list of ids. Let's find and remove it: | |
var newIds = _.union(this[thisKeyName], modelIds); | |
// Set to model | |
var newProps = {}; | |
newProps[thisKeyName] = newIds; | |
this.updateProperties(newProps); | |
// Return filteded Ids | |
return newIds; | |
} | |
} | |
module.exports = belongsToMany; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment