sails.js One to many associations -- TypeError: Cannot convert null to object - sails.js

I am getting this strange error recently. It was not there earlier and I don't remember changing much.
error: Error (E_UNKNOWN) :: Encountered an unexpected error
TypeError: Cannot convert null to object
at hasOwnProperty (native)
at utils.object.hasOwnProperty (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/lib/utils.js:28:14)
at /home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/where.js:259:11
at Array.forEach (native)
at WhereBuilder.complex (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/where.js:177:36)
at complexWhere (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/index.js:244:16)
at find (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-sequel/sequel/index.js:85:23)
at Cursor.populateBuffers [as $populateBuffers] (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/lib/adapter.js:539:31)
at Cursor.run (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-cursor/cursor/cursor.js:45:8)
at runJoins (/home/mandeep/freelance/hellos/node_modules/sails-postgresql/node_modules/waterline-cursor/index.js:51:10)
Details: TypeError: Cannot convert null to object
The error goes away when I remove the one to many association from user model. Here are the models for reference:
Underlying database is postgres
User.js
module.exports = {
tableName: "users",
attributes: {
name: {
type: "string",
required: false
},
permission: {
type: "integer",
defaultsTo: 2
},
primary_phone: {
model: "phone",
required: true
},
phone: {
collection: "phone",
via: "id"
},
primary_email: {
model: "email",
required: true
},
email: {
collection: "email",
via: "id"
}
}
};
Phone.js
module.exports = {
attributes: {
number: {
type: "string",
required: true
},
owner: {
model: "user"
}
}
};
Email.js
module.exports = {
attributes: {
email: {
type: "email",
required: true
},
owner: {
model: "user"
},
verified: {
type: "boolean",
defaultsTo: false
}
}
};

I don't think you can do via: "id" - the id field doesn't refer back to the User model. You should create a new attribute for both the Email and Phone model and link those back to the User model.
For example,
User.js:
...
phone: {
collection: "phone",
via: "nonPrimaryPhoneOwner"
},
email: {
collection: "email",
via: "nonPrimaryEmailOwner"
}
...
Email.js:
...
nonPrimaryEmailOwner: {
model: "user"
}
...
Phone.js:
...
nonPrimaryPhoneOwner: {
model: "user"
}
...

Related

SailsJs/Postgresql - How to create a one way association or one-to-many relation via an unique field

I have two models:
PdfAnnotation.js:
module.exports = {
tableName: "pdf_annotations",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true
},
annotation_id: {
type: "string",
unique: true,
required: true,
},
comments: {
collection: "pdfcomments",
via: "fk_annotation_id"
}
}
};
PdfComments.js:
module.exports = {
tableName: "pdf_comments",
primaryKey: "pk_id",
attributes: {
pk_id: {
type: "number",
autoIncrement: true,
},
fk_annotation_id: {
model: "pdfannotations",
},
comment_content: {
type: "string",
},
}
};
When I run these codes:
PdfAnnotations.create({
annotation_id: "test3",
});
PdfComments.create({
fk_annotation_id: 'test3',
comment_content: 'test',
});
I got this error:
I have followed the documentation: https://sailsjs.com/documentation/concepts/models-and-orm/associations/one-to-many.
The difference between my implementation and the docs is: the constraint I used for PdfComments to PdfAnnotations via an unique field annotation_id(string) not the primary key pk_id(number), so that I got the error.
For some reasons I don't want to use annotation_id as a primary key (such as its type is string)
I'm not familiar with Sails and its ORM, hope to see your help.
Try something like this:
const pdfannotation = await PdfAnnotations.create({
annotation_id: 'test3',
}).fetch();
const pdfcomment = await PdfComments.create({
fk_annotation_id: pdfannotation.id,
comment_content: 'test',
});

Sailsjs Update model Mongodb

I have two collections; user and address. Address collection has association with user collection.
module.exports = {
attributes: {
email: {
type: 'email',
required: true,
unique: true
},
cart: {
collection: 'cart',
via: 'user'
},
isAdmin : {
type : 'boolean',
defaultsTo : false
},
}
module.exports = {
attributes: {
user: {
model: 'user',
required: true
},
address: {
type: 'string',
},
addressAdditional: {
type: 'string',
},
city: {
type: 'string',
},
state: {
type: 'json',
},
zip: {
type: 'string',
},
}
I have the userId and address info passed from the UI and I would like to update the address collection. I tried the following snippet but it does not seem like the data is getting updated.
var address = {
address: "123",
city: "Test City",
state: "NY",
zip: "12345"
};
User.findOne({user:userId}).then(function(model){
Address.update({id:model.id}, address)});
What am I doing wrong? Thanks
After looking in to the sails adapter.js javascript, a function called mongo.objectId to create an ObjectId.
var addressObjectId = mongo.objectId(model.id);
Address.update({_id:addressObjectId}, address)})
https://github.com/balderdashy/sails-mongo/blob/master/lib/adapter.js#L266

Sails.js attribute type array in waterline mongoDB

I want to create a model like below. users model having attribute agreements of type array.I was not able to find a example in waterline where attributes type is an array of object. Please advise
`
module.exports = {
attributes: {
userName: {
type: "string",
unique: true,
required: true
},
Name: {
type: "string",
required: true,
minLength: 2
},
phone: {
type: "string",
required: true
},
password: {
type: "string",
minLength: 6
},
roles: {
type: "array",
required: true,
enum: ['Admin', 'User']
},
agreements: {
type : "array",
agreement :{
version : "string",
dateSigned :"date",
}
},
`
Use one to many association.
Assume that your model is Model.js
agreements: { collection: 'Agreement', via : 'model' }
Create Agreement.js in models
module.exports: {
attributes: {
model : { model: 'Model' },
version : { type: 'string' },
dateSigned : { type: 'datetime' }
}
}
See this documentation.

Non-unique add() to an many-to-many connection

Is it possible to add multiple of the same object to the many-to-many connection? The current setup i am running gives me an Error: Trying to '.add()' an instance which already exists! everytime i try to add a speaker multiple times. For example, maybe speaker X speaks for 20 min, Speaker Y takes over, and then its speaker X:s turn again. How can i solve this?
this is my event model:
attributes: {
id: {
type: "integer",
primaryKey: true,
autoIncrement: true
},
name: {
type: "string",
required: true
},
speakers: {
collection: "speaker",
via: 'events',
dominant: true
}
},
addSpeaker: function (options, cb) {
Event.findOne(options.id).exec(function (err, event) {
if (err) return cb(err);
if (!event) return cb(new Error('Event not found.'));
event.speakers.add(options.speaker);
event.save(cb);
});
And also an Speaker model:
attributes: {
name: {
type: "string",
required: true
},
title : {
type: "string"
},
event: {
model: "event"
},
events: {
collection: "event",
via: "speakers"
}
}

Waterline, error when trying to create one-to-many association

I have these models:
// Material.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
source_info: {
type: 'string',
required: true
},
category: { model: 'category_mat' }
}
};
and:
// Category_Mat.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
but when I run the app I get this error:
/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82
throw new Error('Trying to access a collection ' + collection + ' that is
^
Error: Trying to access a collection category_mat that is not defined.
at ForeignKeys.findPrimaryKey (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82:11)
at ForeignKeys.replaceKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:53:27)
at new ForeignKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:30:10)
at new module.exports (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema.js:30:17)
at Waterline.initialize (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline.js:106:17)
at buildORM (/usr/local/lib/node_modules/sails/lib/hooks/orm/build-orm.js:48:15)
at Array.async.auto.instantiatedCollections [as 1] (/usr/local/lib/node_modules/sails/lib/hooks/orm/index.js:191:11)
at listener (/usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:465:46)
at /usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:419:17
at Array.forEach (native)
I used this documentation as reference:
http://sailsjs.org/#/documentation/concepts/ORM/Associations/OnetoMany.html
so I don't know what I'm missing or if there is a configuration that I have to do... any help?
Maybe it is because "category-mat" used on Material.js is not defined anywhere... try
// Category_Mat.js
module.exports = {
identity: 'category_mat',
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
If this works the only side effect is that even if you have config/globals.js/models set to "true", you won't be able to access the model in the controllers by using "Category_Mat". You will either have to use "sails.models.category_mat" or just "category_mat".