Sails'afterCreate(obj):对象不被更新

这篇文章有3个更新,可能会很长。 请参阅原文章节。

更新3 – 完整的Annonce代码

请注意,这是我目前的代码。 我已经更新了url()方法,并在afterCreate()内部注释了一切。 但代码仍然是一样的。 (对不起,这只是复制粘贴,所以评论用法语)。

 /** * Annonce.js * * @description :: TODO: You might write a short summary of how this model works and what it represents here. * @docs :: http://sailsjs.org/#!documentation/models */ module.exports = { tableName: 'annonce', autoPK: true, attributes: { qte_commande: { type: 'integer', defaultsTo: 1, required: true }, date_mise_en_ligne: 'date', taille_echantillon: { type: 'string', enum: ['P', 'M', 'G'] // TODO : entité }, qte_echantillons_ini: { type: 'integer', required: true, defaultsTo: 1 }, qte_echantillons: { type: 'integer' }, titre_annonce: { type: 'text', required: true }, texte_annonce_md: { type: 'text', required: true }, slug: { type: 'string', unique: true }, prix: { type: 'float', required: true }, /* * Associations */ utilisateur: { model: 'utilisateur' }, variete: { model: 'variete' }, echantillons: { collection: 'echantillon', via: 'annonce' }, /* * Méthode d'instance */ url: function(bool_url_courte) { // Si la variété n'est pas accessible, on ne peut pas connaître son URL. // Dans ce cas il ya un problème, mais on peut toujours donner l'url courte. if (!this.variete) { sails.log.warn(new Error('Variété non accessible depuis Annonce.url().')); bool_url_courte = true; } // Si le slug n'existe pas, on le génère à la volée. if (!this.slug) { var slug = Variete.genSlug(this.titre_annonce); // On va remplir le champ slug, qui doit être unique sails.log.verbose('Après la création d\'annonce : ' + this.id); sails.log.verbose('Le slug vaut : ' + slug); // On va donc rechercher une annonce qui comporte // déjà un tel slug. // Si on ne trouve pas, on pourra faire // attrs.slug = slug; // Si on trouve quelque chose, alors il faudra allouer // attrs.slug = slug + '_' + attrs.id (ce qui est le seul // moyen facile pour obtenir une chaîne unique). // On copie this vers ann_orig car this passe à undefined dans // Annonce.findOne(). var ann_orig = this; Annonce.findOne({slug: slug}, function(err1, ann) { if (err1) { sails.log.error(err1); // Erreur de communication avec la BDD. // On renvoie vers /erreur return '/erreur'; } else if (!ann) { // Chouette, c'est la première annonce avec ce titre. sails.log.verbose('C\'est la première annonce de ce nom : ' + ann_orig.titre_annonce); ann_orig.slug = slug; ann_orig.save(function(err2) { if (err2) { sails.log.error('Erreur durant la sauvegarde de annonce.slug : ' + ann_orig.id + ' / ' + ann_orig.slug, err2); // On renvoie quand-même vers /erreur return '/erreur'; } else { sails.log.info('Annonce /a/' + ann_orig.id + ' <---> slug = ' + ann_orig.slug); } }); } else { // Malheur, on a trouvé quelque chose, donc ce // slug n'est pas unique. sails.log.verbose('Il existe une autre annonce avec ce titre : ' + ann_orig.titre_annonce); ann_orig.slug = slug + '_' + ann_orig.id; ann_orig.save(function(err4) { if (err4) { sails.log.error('Erreur durant la sauvegarde de annonce.slug : ' + ann_orig.id + ' / ' + ann_orig.slug, err4); } else { sails.log.info('Annonce /a/' + ann_orig.id + ' <---> slug = ' + ann_orig.slug); } }); } }); } // fin génération du slug. // Si la variété n'a pas de slug ou si on veut une url courte // alors on renvoie /a/:id // Sinon l'url est /annonce/variete.slug/annonce.slug // // TODO IMPORTANT : Lors du premier appel à cette fonction, il ya // un update en base de donnée fait de manière asynchrone. Du coup, // this.slug n'est peut-être pas encore généré. Il le sera la prochaine fois. if (!this.slug || !this.variete.slug || bool_url_courte){ return '/a/' + this.id; } else { // L'annonce a ce qu'il faut return '/annonce/' + this.variete.slug + '/' + this.slug; } } }, /* * beforeCreate() : on met à jour : * - qte_echantillons * * TODO IMPORTANT : le slug n'existe pas encore. En effet, slug doit être unique, * or pour être unique il faut pouvoir s'assurer que titre_annonce est unique. * Si ce n'est pas le cas, on rajoute '_' + this.id. * Malheureusement, dans beforeCreate() l'id n'est pas encore connu. * Dans afterCreate() on ne peut plus mettre à jour l'objet, donc c'est dans * la méthode d'instance url() qu'on en fait la mise à jour. * * C'est une rustine. */ beforeCreate: function(attrs, next) { // Au début, la qté d'échantillons est la même // que la qté initiale. attrs.qte_echantillons = attrs.qte_echantillons_ini; next(); }, afterCreate: function(attrs, next) { next(); /* // On va remplir le champ slug, qui doit être unique var slug = attrs.titre_annonce.replace(/\s+/g, '-').toLowerCase(); sails.log.verbose('Après la création d\'annonce : ' + attrs.id); sails.log.verbose('Le slug vaut : ' + slug); // On va donc rechercher une annonce qui comporte // déjà un tel slug. // Si on ne trouve pas, on pourra faire // attrs.slug = slug; // Si on trouve quelque chose, alors il faudra allouer // attrs.slug = slug + '_' + attrs.id (ce qui est le seul // moyen facile pour obtenir une chaîne unique). Annonce.findOne({slug: slug}, function(err1, ann) { if (err1) { sails.log.error(err1); next(err1); } else if (!ann) { // Chouette, c'est la première annonce avec ce titre. sails.log.verbose('C\'est la première annonce de ce nom.'); Annonce.update({id:attrs.id}, {slug:slug}).exec(function(err2, object){ sails.log.error('Infinite loop ? (1)'); if (err2) next(err2); else { sails.log.error('Infinite loop ? (3)'); next(); } }); //attrs.slug = slug; //next(); } else { // Malheur, on a trouvé quelque chose, donc ce // slug n'est pas unique. sails.log.verbose('Il existe une autre annonce avec ce titre.'); Annonce.update({id:attrs.id}, {slug: slug + '_' + attrs.id}).exec(function(err4, object){ sails.log.error('Infinite loop ? (2)'); if (err4) next(err4); else next(); }); } }); */ }, beforeUpdate: function (attrs, next) { // On ne met pas à jour le slug, qui doit vivre // pendant toute la vie de l'annonce. next(); } }; 

更新2 – 使用Annonce.update()方法

您将在下面看到我现在必须更新afterCreate()部分中的对象的代码。 请注意, 这是行不通的 。 请求挂起,我看不到Infinite loop ? (*) Infinite loop ? (*) 。 经过检查,我看到过程进入// We didn't find any, so .slug is simple线。

知道什么? 我猜测Model.afterCreate()更新对象是为时已晚。

总而言之,我的问题实际上很简单:我想要一个独特的Annonce.idAnnonce.id添加到它是一个好办法。 这个slug被用来生成一个名为ann.url()的实例方法的URL(参见这个讨论 )。

现在,如果我没有误解,在beforeCreate()里面没有this.idattrs.id 。 这就是为什么我需要在数据库中推入对象后才能做到这一点。

不希望为 slug 添加一个随机的散列/数字 ,因为它会产生一个丑陋的URL,并不能确保我得到一个独特的slu((注意我可以进入一个recursionsearch,这可能是好的) 。

也许afterCreate()是做错的地方,但是文档并没有明确的区分它(再次,由于实现或缺less文档 ,我并不孤单)。

我曾想过更新我的ann.url()方法中的ann.url() 。 这显然有效 。 但是如果我不能做其他的事情,我会select使用这个解决方法:这个方法在我的模板中被调用,所以它是最经常使用的20%代码的一部分(这个项目需要相对较高的性能)。 所以我不想在这个方法中再添加一个条件块。

 afterCreate: function(attrs, next) { // slug must be unique var slug = attrs.titre_annonce.replace(/\s+/g, '-').toLowerCase(); // Let's search for a classified that would have such a slug // If we don't find, we can do // this.slug = slug; // If we find sthg, we must get a unique string. // this.slug = slug + '_' + this.id // This would fit. // findOne() <--- because we only want to see if there's sthg Annonce.findOne({slug: slug}, function(err1, ann) { if (err1) { sails.log.error(err1); next(err1); } else if (!ann) { // We didn't find any, so .slug is simple Annonce.update({id:attrs.id}, {slug: slug}).exec(function(err2, object){ sails.log.error('Infinite loop ? (1)'); if (err2) next(err2); else { sails.log.error('Infinite loop ? (3)'); next(); } }); } else { // We found sthg, so slug is not unique. Annonce.update({id:attrs.id}, {slug: slug + '_' + attrs.id}).exec(function(err3, object){ sails.log.error('Infinite loop ? (2)'); if (err3) { sails.log.error('SAVE ERROR'); next(err3); } else next() }); } }); }, 

更新1 – 使用Annonce.find()方法

我更新了我的Model.afterCreate()来获取数据库中新创build的logging。

 afterCreate: function(attrs, next) { // slug must be unique var slug = attrs.titre_annonce.replace(/\s+/g, '-').toLowerCase(); // Let's search for a classified that would have such a slug // If we don't find, we can do // this.slug = slug; // If we find sthg, we must get a unique string. // this.slug = slug + '_' + this.id // This would fit. // findOne() <--- because we only want to see if there's sthg Annonce.findOne({slug: slug}, function(err, ann) { if (err) { sails.log.error(err); next(err); } else if (!ann) { // We didn't find any, so .slug is simple Annonce.findOne({id:attrs.id}, function(error, object){ sails.log.error('Infinite loop ? (1)'); if (error) next(error); else { sails.log.error('Infinite loop ? (3)'); object.slug = slug; object.save(function (err) { sails.log.error('Infinite loop ? (4)'); next(); }); } }); } else { // We found sthg, so slug is not unique. Annonce.findOne({id:attrs.id}, function(error, object){ sails.log.error('Infinite loop ? (2)'); if (error) { sails.log.error('SAVE ERROR'); next(error); } else { object.slug = slug + '_' + attrs.id; sails.log.error('SAVE OK'); object.save(function (err) { next(); }); } }); } }); }, 

我得到这个:

错误:无限循环? (1)
错误:无限循环? (3)

我没有得到任何SAVE ERROR也没有SAVE OK并请求stucks,我想因为我们不进入save()并没有调用next()

所以有什么问题?


原帖

在我的一个实体中创buildlogging后,我必须添加一个新的字段。 我必须这样做,因为我需要logging的ID。

我需要保存这个,我不知道该怎么做。

 afterCreate: function(obj, next) { // slug field must be unique var slug = obj.titre_annonce.replace(/\s+/g, '-').toLowerCase(); // Let's search for a classified that would have such a slug // If we don't find, we can do // this.slug = slug; // If we find sthg, we must get a unique string. // this.slug = slug + '_' + this.id // This would fit. // findOne() <--- because we only want to see if there's sthg Annonce.findOne({slug: slug}, function(err, ann) { if (err) { sails.log.error(err); next(err); } else if (!ann) { // We didn't find any, so .slug is simple obj.slug = slug; obj.save(function(err){ next(); }); } else { // We found sthg, so slug is not unique. obj.slug = slug + '_' + obj.id; obj.save(function (err) { next(); }); } }); 

错误: obj没有save()方法。 但不使用.save()结束,没有数据库更新。

你怎么看?

在你的例子中,“obj”不会有附加的保存方法。 如果需要保存方法,则需要重新实例化对象。 假设“obj”来自“Model”

例:

 afterCreate : function(obj,next){ Model.findOne(obj.id, function(err, objectWithSaveMethod){ ..... } } 

或者,而不是obj.save(),你可以

 Model.update({slug:slug}, {id:obj.id}, function(err, object){ if(err) next(err); next(); })