2015-03-07 7 views
7

Ho due modelli (Individuale, Email) e sto provando ad inserirmi nella tabella "Individual_Email" creata usando i comandi Sequelize. Mentre Sequelize sta creando la tabella desiderata, restituisce il seguente errore quando si tenta di aggiungere/ottenere/impostare su/da quella tabella: "Oggetto [oggetto Promise] non ha alcun metodo 'addEmail'". Cosa mi manca?Node.js/Sequelize.js/Express.js - Come inserire nell'associazione many-to-many? (sync/async?)

La documentazione Sequelize indica se i modelli sono Utente e Progetto, "Ciò aggiungerà metodi getUsers, setUsers, addUsers a Project e getProjects, setProjects e addProject all'utente."

Questo mi porta a credere (guardando le promesse) che probabilmente non capisco come usare le caratteristiche asincrone del Nodo. Ho provato sia una versione sincrona che asincrona dell'inserimento, restituendo entrambi lo stesso messaggio sopra.

Sequelize Documentazione: http://docs.sequelizejs.com/en/latest/docs/associations/

Codice:

percorsi/index.js

var express = require('express'); 
var router = express.Router(); 
var models = require('../models'); 

/* GET home page. */ 
router.get('/', function(req, res, next) { 
    'use strict'; 

    var tIndividual, tEmail; 
    tIndividual = models.Individual.create({ 
     name: "Test" 
    }); 
    tEmail = models.Email.create({ 
     address: "[email protected]" 
    }); 
    console.log(tEmail); 

    res.render('index', { title: 'Express' }); 
}); 

module.exports = router; 

O

/* GET home page. */ 
router.get('/', function(req, res, next) { 
    'use strict'; 

    var tIndividual, tEmail;  
    tIndividual = models.Individual.create({ 
     name: "Test" 
    }).then(function(){ 
     tEmail = models.Email.create({ 
      address: "[email protected]" 
     }).then(function(){ 
      tIndividual.addEmail(tEmail).then(function(){ 
       console.log("Success"); 
      }); 
     }) 
    }); 

    res.render('index', { title: 'Express' }); 
}); 

module.exports = router; 

modelli/index.js

db.Individual.hasMany(db.Email, { 
    as: 'Email', 
    through: 'Individual_Email' 
}); 
db.Email.hasMany(db.Individual, { 
    as: 'Individual', 
    through: 'Individual_Email' 
}); 

Come posso aggiungere alla tabella 'Individual_Email' nel migliore dei modi? Suppongo di dover fare in modo sincrono per attendere l'aggiornamento, ma sono aperto a qualsiasi suggerimento. Grazie!

risposta

8

Quando si chiama .save() o .create() o altri metodi che restituiscono una promessa, si dovrebbe chiamare .then() su quella promessa. Quando si risolve, cioè quando l'oggetto viene salvato/creato/qualcosa-escluso, verrà chiamata la tua funzione then e riceverà come oggetto l'oggetto salvato/creato.

Così il vostro primo tentativo potrebbe essere riscritto come:

models.Individual.create({ 
    name: "Test" 
}).then(function(createdIndividual) { // note the argument 
    models.Email.create({ 
    address: "[email protected]" 
    }).then(function(createdEmail) { // note the argument 
    createdIndividual.addEmail(createdEmail) 
     .then(function(addedEmail) { // note th-- well you get the idea :) 
     console.log("Success"); 
     }); 
    }) 
}); 

Il codice di cui sopra manca un paio di cose importanti, come ad esempio return ing le promesse per una migliore concatenamento e gestione degli errori, ma è un inizio.Mi consiglia Bluebird's documentation sulla questione (che è la libreria promessa che Sequelize utilizza, ma ci sono molti altri)

+0

Puoi aggiungere il tempo in cui l'email viene creata in un solo colpo? invece di creare prima quindi aggiungereEmail? –

+0

@MortezaShahriariNia Si noti che questa associazione è N: M, poiché sia ​​l'individuo che l'e-mail sono stati configurati con 'hasMany'. Quindi alla fine ci sono tre tabelle (Email, Individuali e EmailIndividuale). Il codice sopra, in pratica, genererà tre istruzioni INSERT e non è possibile ottenere di meno perché ci sono tre tabelle da compilare. –

+0

@MortezaShahriariNia Detto questo, una volta ho avuto una situazione simile che ho risolto in questa domanda: http://stackoverflow.com/questions/28751483/is-there-a-shortcut-in-sequelize-for-user-setgroups-when -i-have-all-the-Grou –

0

Ho capito come risolverlo in un modo, ma fammi sapere se c'è un modo migliore.

La mia soluzione: Dal .create() ha restituito una promessa, ho invece usato .build() che ha restituito un esempio, e solo aggiunto 'Individual_Email' dopo che entrambi erano stati salvati in modo sincrono. Ho quindi chiamato il metodo add sull'istanza restituita da .build() e inserita nella tabella.

Il mio codice:

var tIndividual, tEmail; 
tIndividual = models.Individual.build({ 
    name: "Test" 
}); 
tEmail = models.Email.build({ 
    address: '[email protected]' 
}); 
tIndividual.save() 
    .success(function(){ 
     tEmail.save() 
     .success(function(){ 
      tIndividual.addEmail(tEmail); 
     }); 
}); 
+0

E ' Probabilmente bette per incatenare i tre anziché per annidarli senza motivo. –

+0

Ehi Puoi aggiungere Email mentre stai costruendo l'oggetto, prima che venga effettivamente creato? La ragione per cui lo chiedo è che voglio assicurarmi che l'intero inserto riesca a farcela altrimenti non si preoccupa nemmeno di creare qualcosa in nessuna tabella –

2

È possibile attenuare le "Pyramid of Doom" utilizzando promesse del modo migliore:

var createdIndividual; 
models.Individual.create({ 
    name: "Test" 
}).then(function(createdIn) { // note the argument 
    createdIndividual = createdIn; 
    return models.Email.create({ 
    address: "[email protected]" 
    }); 
}).then(function(createdEmail) { // note the argument 
    return createdIndividual.addEmail(createdEmail); 
}).then(function(addedEmail) { // note th-- well you get the idea :) 
    console.log("Success"); 
});