2016-01-14 44 views
0

我試圖驗證我的模型中的外鍵,當我POST新記錄。 我的關係有「options」:{「validate」:true,「forceId」:false}。環回外鍵驗證

但是,當我POST新對象時,插入新記錄時返回OK和關係對象的inválidID。

{ 
    "name": "Neighborhood", 
    "base": "PersistedModel", 
    "idInjection": true, 
    "options": { 
    "validateUpsert": true 
    }, 
    "properties": { 
    "name": { 
     "type": "string", 
     "required": true 
    }, 
    "address": { 
     "type": "string" 
    } 
    }, 
    "validations": [], 
    "relations": { 
    "country": { 
     "type": "belongsTo", 
     "model": "Country", 
     "foreignKey": "", 
     "options": { 
     "validate": true, 
     "forceId": false 
     } 
    }, 
    "employees": { 
     "type": "hasMany", 
     "model": "Employee", 
     "foreignKey": "" 
    } 
    }, 
    "acls": [   
    ], 
    "methods": {} 
} 

{ 
    "name": "Employee", 
    "base": "PersistedModel", 
    "idInjection": true, 
    "options": { 
    "validateUpsert": true 
    }, 
    "properties": { 
    "name": { 
     "type": "string", 
     "required": true 
    }, 
    "lastName": { 
     "type": "string", 
     "required": true 
    }, 
    "rol": { 
     "type": "string", 
     "required": true 
    }, 
    "birthDate": { 
     "type": "date" 
    } 
    }, 
    "validations": [], 
    "relations": { 
    "neighborhood": { 
     "type": "belongsTo", 
     "model": "Neighborhood", 
     "foreignKey": "", 
     "options": {   
     "validate": true, 
     "forceId": false 
     } 
    } 
    }, 
    "acls": [], 
    "methods": {} 
} 

感謝您的幫助。

+0

我敢肯定的'validate'選項僅適用於嵌入式關係。 – jakerella

+0

好的。所以我應該手動實施。你有「保存前」動作或類似的例子嗎?謝謝。 – Nacho

+0

有什麼幫助?我試着嵌入關係,但不適合我。謝謝。 – Nacho

回答

0

正如我在我的評論中提到的,我不認爲這些選項會以您使用它們的方式進行任何操作,它們僅適用於嵌入式關係。相反,你可能需要使用一個before save操作鉤:

Neighborhood.observe('before save', function verifyForeignKeys(ctx, next) { 
    if (ctx.instance) { // for single model update 
    // check ctx.instance.fkField 
    if (theKeyisNotValid) { 
     return next(new Error('Bad foreign key...')); 
    } 
    } else { // for multi-model update 
    // check ctx.data.fkField 
    } 
    next(); 
}); 
0

感謝@jakerella,It's工作。下面是完整的示例:

module.exports = function (Neighborhood) { 

    Neighborhood.observe('before save', function verifyForeignKeys(ctx, next) { 
     if (ctx.instance) { // for single model update 
      // check ctx.instance.fkField 
      var s = ctx.instance; 
      var countryId = s.__data.countryId;    

      //Get the Application object which the model attached to, and we do what ever we want 
      Neighborhood.getApp(function (err, app) { 
       //App object returned in the callback 
       //PersistedModel.exists(id, callback ((err, exists))) 
       app.models.Country.exists(countryId, function (err, exists) { 
        if (err) throw err; 
        if (!exists) 
         return next(new Error('Bad foreign key...')); 
       }); 
      }); 
      next(); 
     }}); 
} 
0

我認爲要做到這一點,最好的辦法是:

Neighborhood.validateAsync('countryId', hasCountryId, { 
    code: 'notFound.relatedInstance', 
    message: 'related instance not found' 
}); 


function hasCountryId(err, next) { 
    // Use the next if countryId is not required 
    if (!this.countryId) { 
     return next(); 
    } 

    var Country = Neighborhood.app.models.Country; 

    Country.exists(this.countryId, function (error, instance) { 
     if (error || !instance) { 
      err(); 
     } 
     next(); 
    }); 
} 
-1

即通過(在法國的評論抱歉)

創建和使用混入可能

/common/mixins/BelongsToIntegrityCheck.js

'use strict' 

let _ = require('lodash'); 

let checkBelongsToIntegrity = function (ctx, next) { 
    if (ctx.instance) { 
    let relations = ctx.Model.definition.settings.relations; 
    let relationsArray = _.map(relations, rel => { 
     return { modelName: rel.model, fk: rel.foreignKey, type: rel.type }; 
    }); 

    /* On utilise Lodash pour transformer l'objet des relations en Tableau de la forme 
     [ 
     { modelName: 'achat', fk: 'achat_id', type: 'belongsTo' }, 
     { modelName: 'FED_AGENT', fk: 'agent_rfagent', type: 'belongsTo' } 
     ] 
    */ 

    let thisModel = ctx.Model; 
    // Le message qui sera renvoyé en cas d'échec de vérification des contraintes d'intégrité 
    let message = ""; 
    // Le tableau des promises correspondant aux requêtes vérifiants les contraintes 
    let promiseArray = []; 

    relationsArray.forEach(function (relation) { 
     if (relation.type == 'belongsTo') { 
     let parentModelName = relation.modelName; 
     let parentModel = thisModel.app.models[parentModelName]; 
     let parentId = ctx.instance[relation.fk]; 

     // On cherche le modèle parent qui correspond à l'id demandé pour le modèle enfant... 
     promiseArray.push(parentModel.findById(parentId).then(function (parentInstance) { 
      if (parentInstance === null) { 
      message += 'No ' + parentModelName + ' with "' + parentId + '" id. '; 
      } 
     })); 

     } 
    } 
    ); 

    /* Une fois que toutes les promesses ont été déterminées et conduisent vers un message en cas de non respect de la contrainte d'intégrité, 
    on les regroupe dans une promesse commune résolue quand toutes sont résolues et qui renvoit le message en cas de non respect de contrainte */ 
    Promise.all(promiseArray) 
     .then(
     function() { 
     next(message); 
     } 
     , console.error) 
     .catch(function (err) { 
     next(err); 
     }); 
    } 
} 

module.exports = function (Model, options) { 
    Model.observe('before save', checkBelongsToIntegrity); 
}; 

/common/mixins/HasManyIntegrityCheck.js

'use strict' 

let _ = require('lodash'); 

let checkHasManyIntegrity = function (ctx, next) { 
    if (ctx.where) { 
    let relations = ctx.Model.definition.settings.relations; 
    let relationsArray = _.map(relations, rel => { 
     return { modelName: rel.model, fk: rel.foreignKey, type: rel.type }; 
    }); 

    /* On utilise Lodash pour transformer l'objet des relations en Tableau de la forme 
     [ 
     { modelName: 'achat', fk: 'achat_id', type: 'belongsTo' }, 
     { modelName: 'FED_AGENT', fk: 'agent_rfagent', type: 'belongsTo' } 
     ] 
    */ 

    let thisModel = ctx.Model; 
    // Le message qui sera renvoyé en cas d'échec de vérification des contraintes d'intégrité 
    let message = ""; 
    // Le tableau des promises correspondant aux requêtes vérifiants les contraintes 
    let promiseArray = []; 

    relationsArray.forEach(function (relation) { 
     if (relation.type == 'hasMany') { 
     let childrenModelName = relation.modelName; 
     let childrenModel = thisModel.app.models[childrenModelName]; 
     let parentId = ctx.where.id; 
     let whereObject = {}; 
     whereObject[relation.fk] = ctx.where.id; 
     // On cherche les enfants éventuels 
     promiseArray.push(childrenModel.find({ 
      where: whereObject 
     }).then(function (data) { 
      if (data.length > 0) { // Si il y a des enfants, on renvoit une erreur 
      message += 'This "' + thisModel.modelName + '" has "' + childrenModelName + '", and can\'t be deleted. '; 
      } 
     })); 

     } 
    } 
    ); 

    /* Une fois que toutes les promesses ont été déterminées et conduisent vers un message en cas de non respect de la contrainte d'intégrité, 
    on les regroupe dans une promesse commune résolue quand toutes sont résolues et qui renvoit le message en cas de non respect de contrainte */ 
    Promise.all(promiseArray) 
     .then(
     function() { 
     next(message); 
     } 
     , console.error) 
     .catch(function (err) { 
     next(err); 
     }); 
    } 
} 

module.exports = function (Model, options) { 
    Model.observe('before delete', checkHasManyIntegrity); 
}; 

而在你的機型:

父模型:

"mixins": { 
    "HasManyIntegrityCheck": {} 
}, 

兒童型號:

"mixins": { 
    "BelongsToIntegrityCheck": {} 
},