Waterline, error when trying to create one-to-many association - sails.js

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".

Related

I have an 'UsageError' on SailsJs with waterline-orm model method '.archive()'

this is error return in postman when i try to archive a record in my Sails backend.
UsageError: Invalid initial data for new records.\nDetails:\n Could not use one of the provided new records: Missing value for required attribute id. Expected a string, but instead, got: undefined\n [?] See https://sailsjs.com/support for help
Please somebody know what this error means? Thanks in advance.
Thanks for your response
My code:
- In controller:
try {
await Laboratory.archive({id: inputs.id});
} catch (error) {
console.log('Error-6 CORE-DELETE_LABORATORY:', error)
exits.failed(`Error-6 CORE-DELETE_LABORATORY: ${error}${inputs.id}`)}
In file config/models.js:
module.exports.models = {
migrate: 'alter',
fetchRecordsOnUpdate: true,
fetchRecordsOnCreate: true,
fetchRecordsOnCreateEach: true,
attributes: {
createdAt: { type: 'ref', columnType: 'datetime', autoCreatedAt: true, },
updatedAt: { type: 'ref', columnType: 'datetime', autoUpdatedAt: true, },
id: { type: 'string', columnName: '_id' },
},
dataEncryptionKeys: {
default: 'dRYQHBf8Zpza2vMS5BB3qcSiLspJP4BG37I2JkP2yYw='
},
cascadeOnDestroy: true
};
Laboratory model:
module.exports = {
attributes: {
type: {
type: 'string',
isIn: ['INSIDE', 'OUTSIDE'],
required: true,
},
raisonSocial: {
type: 'string',
required: true,
unique: true,
},
city: {
type: 'string'
},
address: {
type: 'string'
},
email: {
type: 'string'
},
neighborhood: {
type: 'string'
},
contacts: {
type: 'string'
},
logo: {
type: 'string'
},
lat: {
description: 'Latitude',
type: 'number'
},
long: {
description: 'Longitude',
type: 'number'
},
website: {
type: 'string',
defaultsTo: ''
},
subdomain: {
type: 'string',
unique: true,
required: true,
},
mobileMoney: {
type: 'string'
},
bank: {
type: 'string',
defaultsTo: ''
},
bankAccountID: {
type: 'string',
defaultsTo: ''
},
validated : {
type: 'boolean',
defaultsTo : false
},
f_establishment: {
model: 'establishment'
},
director: {
description: 'Chef of laboratory id',
type: 'json',
example: '{name, phone, role}',
required: true,
}
},
customToJSON () {
if (this.logo) {
this.logo = `${process.env.BASE_URL}/avatar/${this.logo}`
}
return this
}
};
Thanks.
Sails throws UsageError when we use a db method in an incorrect way. To be more precise, this is what Sails has in its documentation.
When an error has name: 'UsageError', this indicates that a Waterline
method was used incorrectly, or executed with invalid options (for
example, attempting to create a new record that would violate one of
your model's high-level validation rules.)
https://sailsjs.com/documentation/concepts/models-and-orm/errors#?usage-errors
To give you a simple example, if you have a db query with limit parameter and you start passing string values for that parameter, Sails with start throwing UsageError.
In your case, things should be self explanatory from the error detail itself. Your code flow is getting undefined for inputs.id when it tries to run Laboratory.archive({id: inputs.id}) but id is expected to be a string if you see config/models.js.
Just do a basic debugging to see why inputs.id is coming as undefined and solve that issue, and you should be good to go.

UUID as primary key in sailsjs domain

I am using Sails.js version 1.0.2. I am trying to assign uuid as primary key throughout the application. I tried putting
id: { type: 'string', defaultsTo:uuid.v4() } in model.js but it's saying Primary keys must be unique therefore can't contain a default value.
_________________EDIT_______________
I tried this code in my domain
beforeCreate: function (modelObj, next) {
modelObj.id = uuidv4.v4();
next();
}
And edit my Model.js configuration is like :
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
}
beforeCreate method never executes and throw the error while creating the record like:
error: Sending 500 ("Server Error") response:
{ UsageError: Invalid new record.
Details:
Missing value for required attribute `id`. Expected a string, but
instead, got: undefined
Please let me know if I am doing anything wrong.
Thanks
You can do something like this instead of giving default value
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
You can add this piece of function in your model. This gets invoked whenever there is a create operation on model.
Your Model.js should looks something like this
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
},
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
Sample code of my Controller and Model,
TestController.js
module.exports = {
create: function(req, res) {
Test.create({"name": "arshad"})
.then(function(result){
res.send("done");
})
}
};
Test.js Model
module.exports = {
attributes: {
id: { type: 'string', required: true },
name: { type: 'string' }
},
beforeCreate: function(obj, next) {
obj.id = 'someId';
next();
}
};
This is how your model and controller will look like. This will add someId as defined in beforeCreate function to the object
In your case you are using uuid package. Check in debugging mode whether uuid reference is available in beforeCreate or not

sails-postgres error: invalid input syntax for type json

I'm building an application in sails.js with postgresql database. The model is:
attributes: {
name: {
type: 'string',
required: true
},
username: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string',
required: true
},
rating: {
type: 'integer'
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
}
Whenever I try to create a new user, I get an error as follows:
sails-postgres error: invalid input syntax for type json.
How can I solve this problem?

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

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"
}
...

Sails.js composite unique field

This model gives me the effect I want at the expense of duplicated data and general uglyness:
//Example
var Example = {
attributes: {
foo: {
type: 'string',
required: true
},
bar: {
type: 'string',
required: true,
},
baz: {
type: 'integer',
required: true,
min: 1
},
foobar: {
type: 'string',
unique: true
}
},
beforeValidation : function(values,cb) {
values.foobar = values.foo+values.bar;
cb();
}
};
module.exports = Example;
Is there a better strategy for creating a composite unique key?
There's no way to do this directly in sails see https://github.com/balderdashy/waterline/issues/221. The best solution is to do this directly in the db you plan to use.