Sails'afterCreate(obj):对象未更新

时间:2014-10-22 12:02:56

标签: node.js sails.js waterline

这篇文章有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 y a 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 y a 
      // 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 ? (*)。检查后,我发现该过程进入// We didn't find any, so .slug is simple行。

知道什么?我想Model.afterCreate()更新对象的时间太晚或太早。

总结一下,我的问题实际上很简单:我想要一个独特的slug,并且添加Annonce.id是一个很好的方法来管理。此slug用于生成具有名为ann.url()的实例方法的URL(请参阅 this discussion )。

现在,如果我没有误解,在beforeCreate()内部没有this.idattrs.id。这就是为什么我需要在数据库中推送对象后才能创建它。

不想在slug中添加一个随机哈希/数字,因为它会生成一个丑陋的url,并且它不能确保我得到一个独特的slug(注意我可以进入进行递归搜索,这可能没问题。

也许afterCreate()是错误的地方,但是文档并没有明确地将其隐藏起来(由于实施或lack in documentation,我并不是唯一一个真正的问题。

我曾想过更新我的ann.url()方法中的slug。这显然有效。但是如果我不能做任何其他事情,我将选择使用此解决方法:此方法在我的模板中随处调用,因此它是最常使用的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()以获取数据库中新创建的记录。

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 ERRORSAVE OK且请求卡住,我认为因为我们没有进入save()而且没有next()被调用。< / p>

那么问题是什么?


原帖

在我的某个实体中创建记录后,我必须添加一个新字段。我必须这样做,因为我需要记录的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()结束而没有数据库更新。

您怎么看?

1 个答案:

答案 0 :(得分:1)

在您的示例中,“obj”不会附加save方法。如果需要save方法,则需要重新实例化对象。假设“obj”来自“模型”

示例:

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();
})