Friday 15 August 2014

node.js - Sails' afterCreate(obj): object is not updated -



node.js - Sails' afterCreate(obj): object is not updated -

this post has 3 updates , may long. please see original post section.

update 3 - total annonce code

note current code. have updated url() method , commented within aftercreate(). code still same. (sorry, it's copy-and-paste, commentaries in french language).

/** * annonce.js * * @description :: todo: might write short summary of how model works , 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 boy url. // dans ce cas il y united nations 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à united nations 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 vers ann_orig auto 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 homecoming '/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 homecoming '/erreur'; } else { sails.log.info('annonce /a/' + ann_orig.id + ' <---> slug = ' + ann_orig.slug); } }); } else { // malheur, on 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 of import : lors du premier appel à cette fonction, il y // united nations update en base of operations 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){ homecoming '/a/' + this.id; } else { // l'annonce ce qu'il faut homecoming '/annonce/' + this.variete.slug + '/' + this.slug; } } }, /* * beforecreate() : on met à jour : * - qte_echantillons * * todo of import : 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à united nations 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 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(); } }; update 2 - using annonce.update() method

you shall see below code have update object within aftercreate() section. note this doesn't work. request hangs , see no infinite loop ? (*). after checking, see process comes // didn't find any, .slug simple line.

know what? guess model.aftercreate() late or update object.

to summerize, problem simple: wanted have unique slug, , adding annonce.id way manage to. slug used generate url instance method named ann.url() (see this discussion).

now, if don't misunderstand, in beforecreate() there no this.id nor attrs.id inside. why need create after pushing object in database.

i wouldn't add together random hash/number slug because generate ugly url, , wouldn't ensure me unique slug (note come in recursive searching , ok).

maybe aftercreate() wrong place this, documentation doesn't secify (once 1 time again not lone true issue due implementation or lack in documentation).

i have thought of updating slug within ann.url() method. obviously works. take utilize workaround if cannot else: method called everywhere within templates, it's part of 20% code used (this project needs relatively high performance). don't want add together 1 more conditional block in method.

aftercreate: function(attrs, next) { // slug must unique var slug = attrs.titre_annonce.replace(/\s+/g, '-').tolowercase(); // let's search classified have such slug // if don't find, can // this.slug = slug; // if find sthg, must unique string. // this.slug = slug + '_' + this.id // fit. // findone() <--- because want see if there's sthg annonce.findone({slug: slug}, function(err1, ann) { if (err1) { sails.log.error(err1); next(err1); } else if (!ann) { // didn't find any, .slug 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 { // found sthg, slug 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() }); } }); }, update 1 - using annonce.find() method

i have updated model.aftercreate() create fetch newly created record in database.

aftercreate: function(attrs, next) { // slug must unique var slug = attrs.titre_annonce.replace(/\s+/g, '-').tolowercase(); // let's search classified have such slug // if don't find, can // this.slug = slug; // if find sthg, must unique string. // this.slug = slug + '_' + this.id // fit. // findone() <--- because want see if there's sthg annonce.findone({slug: slug}, function(err, ann) { if (err) { sails.log.error(err); next(err); } else if (!ann) { // didn't find any, .slug 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 { // found sthg, slug 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(); }); } }); } }); },

i this:

error: infinite loop ? (1) error: infinite loop ? (3)

i don't save error nor save ok , request stucks, think because don't come in save() , no next() called.

so what's problem?

original post

after creating record in 1 of entities, have add together new field. have after because need record's id.

i need save , don't know how do.

aftercreate: function(obj, next) { // slug field must unique var slug = obj.titre_annonce.replace(/\s+/g, '-').tolowercase(); // let's search classified have such slug // if don't find, can // this.slug = slug; // if find sthg, must unique string. // this.slug = slug + '_' + this.id // fit. // findone() <--- because want see if there's sthg annonce.findone({slug: slug}, function(err, ann) { if (err) { sails.log.error(err); next(err); } else if (!ann) { // didn't find any, .slug simple obj.slug = slug; obj.save(function(err){ next(); }); } else { // found sthg, slug not unique. obj.slug = slug + '_' + obj.id; obj.save(function (err) { next(); }); } });

error: obj doesn't have save() method. not using .save() ends no database update.

what think?

in example, "obj" not have save method attached. need re-instantiate object if want save method. assuming "obj" came "model"

example:

aftercreate : function(obj,next){ model.findone(obj.id, function(err, objectwithsavemethod){ ..... } }

or instead of obj.save() could

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

node.js sails.js waterline

No comments:

Post a Comment