Skip to content

Commit

Permalink
Added support for multiple associate as per issue #4
Browse files Browse the repository at this point in the history
Lucid now supports multiple associate and dissociate under single write operation
  • Loading branch information
thetutlage committed Oct 17, 2015
1 parent 45f4740 commit 6aeba8a
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 304 deletions.
16 changes: 8 additions & 8 deletions src/Orm/Proxy/Model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Model {
this.attributes = attributes ? helper.mutateRow(this, attributes) : {}

/**
* here we create an isolated connection to
* here we create an isolated connection to
* the database, one per model instance.
*/
this.connection = this.constructor.database.table(this.constructor.table)
Expand Down Expand Up @@ -104,7 +104,7 @@ class Model {
*/
update () {
/**
* one can only update existing model. Here we make
* one can only update existing model. Here we make
* sure this model is initiated after db fetch.
*/
if (!helper.isFetched(this)) {
Expand All @@ -124,7 +124,7 @@ class Model {
*/
delete () {
/**
* one can only delete existing model. Here we make
* one can only delete existing model. Here we make
* sure this model is initiated after db fetch.
*/
if (!helper.isFetched(this)) {
Expand All @@ -144,7 +144,7 @@ class Model {
const self = this

/**
* one can only delete existing model. Here we make
* one can only delete existing model. Here we make
* sure this model is initiated after db fetch.
*/
if (!helper.isFetched(this)) {
Expand Down Expand Up @@ -302,7 +302,7 @@ class Model {

/**
* relation scopes are nested queries on relationship models, they are
* not required by model instance, but required when fetching
* not required by model instance, but required when fetching
* relationships using with method.
* @type {Object}
*/
Expand Down Expand Up @@ -379,7 +379,7 @@ class Model {

/**
* relation scopes are nested queries on relationship models, they are
* not required by model instance, but required when fetching
* not required by model instance, but required when fetching
* relationships using with method.
* @type {Object}
*/
Expand Down Expand Up @@ -448,7 +448,7 @@ class Model {

/**
* relation scopes are nested queries on relationship models, they are
* not required by model instance, but required when fetching
* not required by model instance, but required when fetching
* relationships using with method.
* @type {Object}
*/
Expand Down Expand Up @@ -538,7 +538,7 @@ class Model {

/**
* relation scopes are nested queries on relationship models, they are
* not required by model instance, but required when fetching
* not required by model instance, but required when fetching
* relationships using with method.
* @type {Object}
*/
Expand Down
24 changes: 12 additions & 12 deletions src/Orm/Proxy/Model/relation.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ relation.associate = function (target,model) {
if(target._associationModel._activeRelation.relation !== 'belongsTo'){
throw new Error(`Unable to call associate on ${target._associationModel._activeRelation.relation}`)
}
target._associationModel._associationAttributes = model.attributes
target._associationModel._associationAttributes.push({attributes:model.attributes,targetPrimaryKey:target._associationModel._activeRelation.targetPrimaryKey,relationPrimaryKey:target._associationModel._activeRelation.relationPrimaryKey})
target.new()
}

Expand All @@ -54,15 +54,15 @@ relation.dissociate = function (target){
if(target._associationModel._activeRelation.relation !== 'belongsTo'){
throw new Error(`Unable to call dissociate on ${target._associationModel._activeRelation.relation}`)
}
target._associationModel._associationAttributes = {dissociate:true}
target._associationModel._associationAttributes.push({attributes:{dissociate:true},targetPrimaryKey:target._associationModel._activeRelation.targetPrimaryKey,relationPrimaryKey:target._associationModel._activeRelation.relationPrimaryKey})
target.new()
}

/**
* @function attach
* @description this method is only belongsToMany specific and will
* attach primary values from 2 models into a pivot table.
* @note this method does not touch host/relational model
* @note this method does not touch host/relational model
* tables. It only make neccessary entries inside
* pivot table
* @param {Object} target [description]
Expand All @@ -74,10 +74,10 @@ relation.attach = function (target, relationValue, extraFields) {

/**
* getting relationship meta data to be used while persisting
* values inside pivot table.
* values inside pivot table.
*/
const getPersistanceFields = relation.getFieldsForAD(target)
const pivotTable = getPersistanceFields.pivotTable
const pivotTable = getPersistanceFields.pivotTable
const pivotPrimaryKey = getPersistanceFields.pivotPrimaryKey
const pivotOtherKey = getPersistanceFields.pivotOtherKey
const targetPrimaryKey = getPersistanceFields.targetPrimaryKey
Expand Down Expand Up @@ -107,7 +107,7 @@ relation.attach = function (target, relationValue, extraFields) {
* @function detach
* @description this method is only belongsToMany specific and will
* remove primary values of 2 models from pivot table.
* @note this method does not touch host/relational model
* @note this method does not touch host/relational model
* tables. It only remove rows from pivot table.
* @param {Object} target [description]
* @param {Number} relationValue [description]
Expand All @@ -117,10 +117,10 @@ relation.detach = function (target, relationValue) {

/**
* getting relationship meta data to be used while removing
* values inside pivot table.
* values inside pivot table.
*/
const getPersistanceFields = relation.getFieldsForAD(target)
const pivotTable = getPersistanceFields.pivotTable
const pivotTable = getPersistanceFields.pivotTable
const pivotPrimaryKey = getPersistanceFields.pivotPrimaryKey
const pivotOtherKey = getPersistanceFields.pivotOtherKey
const targetPrimaryKey = getPersistanceFields.targetPrimaryKey
Expand Down Expand Up @@ -153,7 +153,7 @@ relation.detach = function (target, relationValue) {

/**
* @description think of it as a real helper method to get values
* required to attach belongsToMany models values inside a
* required to attach belongsToMany models values inside a
* pivot table.
* @method getPersistanceFields
* @param {Object} target [description]
Expand Down Expand Up @@ -267,8 +267,8 @@ relation.resolveHasMany = function (values, relationDefination) {

/**
* @function resolveBelongsToMany
* @description setting up model with initial query params for
* belongsToMany. It returns query builder which can be
* @description setting up model with initial query params for
* belongsToMany. It returns query builder which can be
* chained further.
* @param {Object} values [description]
* @param {Object} relationDefination [description]
Expand Down Expand Up @@ -337,7 +337,7 @@ relation.resolveBelongsToMany = function (values, relationDefination) {
]

/**
* we set the pivot table here. This will be used by fetch
* we set the pivot table here. This will be used by fetch
* method to fetch extra pivot columns defined by user.
* @type {String}
*/
Expand Down
78 changes: 38 additions & 40 deletions src/Orm/Proxy/Static/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class StaticProxy {
Model.activeConnection = Database.table(Model.table)

/**
* here we store active relation as an object which
* has useful information like
* here we store active relation as an object which
* has useful information like
* relational model
* foreign key
* other key
Expand All @@ -34,15 +34,15 @@ class StaticProxy {
Model._activeRelation = {}

/**
* here we store relation keys to be fetched when fetching
* here we store relation keys to be fetched when fetching
* host/target model. In short these are keys sent with
* `with` method
* @type {Array}
*/
Model._relations = []

/**
* here we store scope methods, which should be executed on
* here we store scope methods, which should be executed on
* relational query builder. We simply store these
* and invoke them when running relational model
* queries.
Expand Down Expand Up @@ -80,18 +80,20 @@ class StaticProxy {
Model._pivotTable = null

/**
* association model to set association attributes on this is required for
* association model to set association attributes on this is required for
* belongsTo method.
* @type {Object}
*/
Model._associationModel = {}

/**
* association attributes to read foreign key value from while saving a
* relation.
* association attributes to read foreign key value from while saving a
* relation. There can be multiple associationAttributes if
* associate of dissociate has been called multiple
* times.
* @type {Object}
*/
Model._associationAttributes = {}
Model._associationAttributes = []

/**
* pivotAttributes are required to save belongsToMany relationship
Expand All @@ -107,29 +109,29 @@ class StaticProxy {
*/
Model.create = function (values, isMutated, connection) {

const self = this
/**
* here we look for an active relation and if that relation is
* belongsTo then we grab associationAttributes set by
* belongsTo then we grab associationAttributes set by
* associate method and grab the value of foreign
* key under relation
*/
if(this._activeRelation.relation === 'belongsTo' && Object.keys(this._associationAttributes).length > 0){
const targetPrimaryKey = this._activeRelation.targetPrimaryKey
const relationPrimaryKey = this._activeRelation.relationPrimaryKey
this._foreignKey[targetPrimaryKey] = this._associationAttributes[relationPrimaryKey]
if(this._associationAttributes.length > 0){
this._associationAttributes.forEach(function (item) {
self._foreignKey[item.targetPrimaryKey] = item.attributes[item.relationPrimaryKey]
})
}

/**
* here we set foreign key and it's value to be inserted
* if create method is invoked via relational model.
*/
if(this._foreignKey && Object.keys(this._foreignKey).length > 0){
const key = Object.keys(this._foreignKey)[0];
values[key] = this._foreignKey[key]
Object.keys(this._foreignKey).forEach(function (index) {
values[index] = self._foreignKey[index]
})
}

return query.create(this, values, isMutated, connection)

}

/**
Expand All @@ -139,38 +141,34 @@ class StaticProxy {
*/
Model.update = function (values, isMutated, connection) {

const self = this

/**
* here we look for an active relation and if that relation is
* belongsTo then we grab associationAttributes set by
* belongsTo then we grab associationAttributes set by
* associate method and grab the value of foreign
* key under relation
*/
if(this._activeRelation.relation === 'belongsTo' && Object.keys(this._associationAttributes).length > 0){

/**
* otherwise set foriegn key value to the value of primary key
* from relational model
*/
const targetPrimaryKey = this._activeRelation.targetPrimaryKey
const relationPrimaryKey = this._activeRelation.relationPrimaryKey

/**
* if dissociate has been called, set foreign key value to null
*/
if(this._associationAttributes.dissociate){
this._foreignKey[targetPrimaryKey] = null
}else{
this._foreignKey[targetPrimaryKey] = this._associationAttributes[relationPrimaryKey]
}

if(this._associationAttributes.length > 0){
this._associationAttributes.forEach(function (item) {
if(item.attributes.dissociate){
self._foreignKey[item.targetPrimaryKey] = null
}
else{
self._foreignKey[item.targetPrimaryKey] = item.attributes[item.relationPrimaryKey]
}
})
}

/**
* here we set foreign key and it's value to be inserted
* if create method is invoked via relational model.
*/
if(this._foreignKey && Object.keys(this._foreignKey).length > 0){
const key = Object.keys(this._foreignKey)[0];
values[key] = this._foreignKey[key]
Object.keys(this._foreignKey).forEach(function (index) {
values[index] = self._foreignKey[index]
})
}

return query.update(this, values, isMutated, connection)
Expand Down Expand Up @@ -216,7 +214,7 @@ class StaticProxy {
this._withPivot = []
this._pivotTable = null
this._associationModel = {}
this._associationAttributes = {}
this._associationAttributes = []
this._pivotAttributes = {}
this.activeConnection = this.database.table(this.table)

Expand Down
4 changes: 2 additions & 2 deletions src/Orm/Proxy/Static/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ proxy.get = function (target, name) {
}

/**
* attaching belongsToMany relationships on pivot tables.
* attaching belongsToMany relationships on pivot tables.
* this method read relation defination and make a
* raw query using `database` property from model
* constructor
Expand All @@ -182,7 +182,7 @@ proxy.get = function (target, name) {


/**
* removing belongsToMany relationships on pivot tables.
* removing belongsToMany relationships on pivot tables.
* this method read relation defination and make a
* raw query using `database` property from model
* constructor
Expand Down
Binary file modified test/implementation/storage/blog.sqlite3
Binary file not shown.
Loading

0 comments on commit 6aeba8a

Please sign in to comment.