0

I am building serverless application using node js and using claudia-api-builder as a framework to launch APIs in AWS.

In app.js file, i call the required api as

const ApiBuilder = require('claudia-api-builder');
const api = new ApiBuilder();
module.exports = api;

api.post('/api/auth/validatephonenumber', async function (request) 
{
    return new Promise((resolve, reject) => {
        index.loadDatabase().then((db) => {
            resolve(loginController.validatePhonenumber(db, request));
        });
    });
});

Below is my code:

async function validatePhonenumber(db, request) {
return new Promise(
    async (resolve, reject) => {
        let emailid;            
        await db.EmailRegistration.sync().then(function () {
             emailid = db.EmailRegistration.findOne({
                where: { email: { [Op.eq]: mailid } },
                attributes: ['id'],
            });
        });
        if (emailid != null) {
            console.log(`email id: ${emailid.id}`);
            await db.ContactDetails.sync().then(function () {
                db.ContactDetails.findOrCreate({
                    where: { contactnumber: phnum },
                    defaults: { EmailRegistrationId: emailid.id },
                }).spread((contactdetails, created) => {
                    console.log(`contactdetails: ${contactdetails}`);
                    if (contactdetails !== null) {
                        resolve({ statuscode: indexController.statusCode.statusOK, contactdetails: contactdetails })
                    } else {
                        reject({ statuscode: indexController.statusCode.InternalServerError, message: 'phone number not created' });
                    }
                });
            });
        };
    });
}

I am trying to add a emailregistrationid of EmailRegistration table into ContactDetails table as a foreign key reference. I am using sequelize with mysql, nodejs to achieve the desired results. But, i am getting below error:

Unhandled rejection SequelizeForeignKeyConstraintError: Cannot add or update a child row: a foreign key constraint fails (inmeeydb.ContactDetails, CONSTRAINT ContactDetails_ibfk_1 FOREIGN KEY (EmailRegistrationId) REFERENCES EmailRegistration (id) ON DELETE CASCADE ON UPDATE CASCADE)

Below is my EmailRegistration models file:

const moment = require('moment');

module.exports = (sequelize, DataTypes) => {
const EmailRegistration = sequelize.define(
'EmailRegistration',
{
  id: {
    type: DataTypes.UUID,
    primaryKey: true,
    allowNull: false,
    defaultValue: DataTypes.UUIDV4,
  },
  email: {
    type: DataTypes.STRING(50),
    allowNull: false,
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: { min: 6 },
  },
  createdAt: {
    type: DataTypes.DATE,
    get() {
      return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
    },
  },
  updatedAt: {
    type: DataTypes.DATE,
    defaultValue: null,       
  },
},
{
  freezeTableName: true,
}
);

EmailRegistration.associate = function (models) {
    EmailRegistration.hasOne(models.ContactDetails,
        { foreignKey: 'EmailRegistrationId' }
    );
};

return EmailRegistration;
};

Below is my Contactdetails models file:

const moment = require('moment');

module.exports = (sequelize, DataTypes) => {
const ContactDetails = sequelize.define(
'ContactDetails',
{
  id: {
    type: DataTypes.UUID,
    primaryKey: true,
    allowNull: false,
    defaultValue: DataTypes.UUIDV4,
  },
  contactnumber: { type: DataTypes.STRING(13), allowNull: false },
  isverified: { type: DataTypes.BOOLEAN, defaultValue: false },
  createdAt: {
    type: DataTypes.DATE,
    get() {
      return moment.utc(new Date(), 'DD/MM/YYYY h:mm a').format('DD/MM/YYYY h:mm a');
    },
  },
  updatedAt: {
    type: DataTypes.DATE,
    defaultValue: null,        
  },
},
{
  indexes: [{ fields: ['contactnumber'], unique: true }],
},
{
  freezeTableName: true,
}
);

ContactDetails.associate = function(models) {
ContactDetails.belongsTo(models.EmailRegistration, {
  onDelete: 'CASCADE',
  hooks: true,
  foreignKey: { allowNull: false },
});
};   


return ContactDetails;
};

I tried to change the code as below with reference in both tables, but nothing worked.

ContactDetails.associate = function(models) {
    ContactDetails.belongsTo(models.EmailRegistration,
    { foreignKey: 'EmailRegistrationId' }
    );
};

Not able to analyze how to overcome the issue. This worked fine when i used nodejs with expressjs and had no issues. It fails to identify the EmailRegistrationId(that is missing in the query) in ContactDetails table and shows the output as

INSERT INTO `ContactDetails` (`id`,`contactnumber`,`isverified`,`createdAt`,`updatedAt`) VALUES ('52974e07-8489-4101-ab71-6af874903290','+xxxxxxxxx',false,'2018-10-12 08:55:35','2018-10-12 08:55:35');
James Z
  • 12,209
  • 10
  • 24
  • 44
Priyanka
  • 95
  • 5
  • 12

1 Answers1

0

You need to update the configuration of your association. The ContactDetails model will now have a field called emailregistrationid

EmailRegistration.associate = function (models) {
  EmailRegistration.hasMany(models.ContactDetails);
};

ContactDetails.associate = function(models) {
  ContactDetails.belongsTo(models.EmailRegistration, {
    onDelete: 'CASCADE',
    hooks: true,
    foreignKey: {
      name: 'emailregistrationid'
      allowNull: false
    },
  });
}

ContactDetails.create({
  ...
  emailregistrationid: <some_valid_emailregistrationid>
})
mcranston18
  • 4,680
  • 3
  • 36
  • 37
  • thanks for your answer. I indeed changed the code to implement it the way you had given. But the above code fails to add a column 'emailregistrationid' in ContactDetails table. It just creates the columns as mentioned in the models file. There is no reference to emailregistrationid in it. Kindly let me know what else needs to be changed. – Priyanka Oct 12 '18 at 16:07
  • Are you using migrations? – mcranston18 Oct 12 '18 at 16:08
  • Currently, i am not using as i have just started to migrate the project and got struck in this issue. – Priyanka Oct 12 '18 at 16:14
  • Its failing to put a reference of EmailRegistration table in ContactDetails table, with whatever the code being changed to. Not quite understanding, what is happening? – Priyanka Oct 12 '18 at 16:20
  • 1
    Thanks a lot for your solution. After lot of debugging i found that, i was missing the Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); part in my index.js file. After adding that, along with the solution you suggested, it worked. Thanks once again. – Priyanka Oct 12 '18 at 19:47