Sailsjs - Prevent non-model fileds to be saved in mongo document - sails.js

I recently started working with Sails and mongo.
I use Sails blueprints to generate part of my api.
The problem is, that the request body I send is being saved to the mongo collection, regardless of the fields defined in the model.
So for example, let's say I have the following Event model:
module.exports = {
attributes: {
title: {
type: 'string',
required: true
},
}
}
When I Send a POST request to the /event/ endpoint with the following params:
{"title":"Some Event", "random":"string"}
The saved mongo document contains also the "random":"string" value, even though it's not part of the model.
I've tried to come up with some common method to remove non-model attributes before creation for all models, but the possible solutions seemed not right and dirty.
Am I missing something?
Any help would be appreciated!

You can use schema option in your model. Just add it to model declaration and that's it.
// api/models/Model.js
module.exports = {
schema: true,
attributes: {
title: {
type: 'string',
required: true
}
}
};

Related

One way association with array of reference _id in sails js

I'm trying to use one way association because I need only to have reference from 1 model to other model but not vice versa.
Model Arts:
module.exports = {
attributes: {
fileName: {type: 'string', required: true},
softwareUsed: {
model: 'Softwares'
}
}
}
Model Softwares:
module.exports = {
attributes: {
name: {type: 'string', required: true}
}
}
This is my api:
http://localhost:1337/api/v1/arts/create
if this is my request body, it works fine:
request body:
{
"fileName": "booking.jpeg",
"softwareUsed": "5e70309cbf12b61299d6c528",
}
but i want to store array of softwareUsed, so i tried:
request body:
{
"fileName": "booking.jpeg",
"softwareUsed": ["5e70309cbf12b61299d6c528", "5e70309cbf12b61299d6c529"],
}
but i got an error with that:
error: OperationalError [UsageError]: Invalid new record.
Details:
Could not use specified `softwareUsed`. Expecting an id representing the associated record, or `null` to indicate there will be no associated record. But the specified value is not a valid `softwareUsed`. Instead of a string (the expected pk type), the provided value is: [ '5e70309cbf12b61299d6c528', '5e70309cbf12b61299d6c529' ]
I also tried to make it array in model:
softwareUsed: [{
model: 'Softwares'
}]
but still don't work.
Is there a way to that in one way association or I need to use other association, but how can I achieve that?
Thank you.
I think you need to label the softwareUsed attribute with a collection, not a model:
module.exports = {
attributes: {
fileName: {type: 'string', required: true},
softwareUsed: {
collection: 'Softwares'
}
}
}
All the documentation on one-to-many in the sails docs involves two-way associations and adding a via attribute, but I think this way works for a one-way association.
Of course, your first api call may now longer work: you may need to wrap the single software id in an array.

sailsjs one-way associations confusion

I am having a hard time wrapping my head around associations with sailsjs.
I have 2 models
Services
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
model: 'users',
via: 'id',
},
},
Users
attributes: {
email: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string'
}
},
So, a service is tied to a user (matching the id of the user).
I used to do a call like http://localhost:1337/Services?userId=userId
Now I would like to transition to associations using the above model attributes.
This works by calling the ID of the service just fine (it includes the users data as well), however if all i have is the user, how could I get the service
Doing the same call (http://localhost:1337/Services?userId=userId) returns and empty object.
Am I forced to actually have a one-to-one or one-to-many association? I don't understand why I can no longer use the userId field (stored in the DB) to do queries once I start using associations. I guess I am looking for the best of both worlds here.
EDIT:
Let me try make this more clear. Before trying to do associations, I could call this URL (using blueprint)
http://localhost:1337/Services?userId=userId
The Services model used to look like this
attributes: {
status: {
defaultsTo: 'inactive'
},
userId:{
type: 'string',
required: true,
},
},
Then when a user is created, a service for that user is created with the userId matching the ID in the Users table.
Now I would like to implement associations using the above model scheme.
However, because (my best guess) the userId field of the service is mapped to the Users model, I am unable to search for a Server using the userId field that is stored.
I hope that makes sense? In another words, tryin to call
http://localhost:1337/Services?userId=userId
returns nothing when using associations but does return a value when I don't use associations

Sails.js add attribute from another table to a model

I am trying to pull an extra attribute for a model from a different table.
I have been trying with associations but it seems wrong to create an extra model and associate that to my original model.
This is my model Company.js
module.exports = {
schema: true,
autoCreatedAt: false,
autoUpdatedAt: false,
autoPK: false,
attributes: {
name: {
type: 'string'
},
url: {
type: 'string'
},
summary: {
type: 'text'
}
}
};
I have another table in MySQL with two columns, crunchbase_url and company_id, I would like to pull the crunchbase_url into the Company model, what would be the best way to do it without migrating the DB (not an option unfortunately).
Thanks,
Well, turns out that the documentation is fine and all works like a charm by simply creating another model and using one to many association with joined with via.
However, there is a bug that threw me off:
When defaultLimit is set to -1, the find action return an empty list if there are associations.

Sails.js - Many-to-Many fails to save

I have a simple need to add tags to patients. I followed the Sails and Waterline documentation concerning many-to-many associations, but it's failing at some point (no errors). I'm using MongoDB for data storage. Code below:
Tag Model
module.exports = {
attributes: {
name: 'STRING',
color: {
type: 'STRING',
defaultsTo: '#777777'
},
tagged: {
collection: 'patient',
via: 'tags',
dominant: true
}
}
};
Patient Model
module.exports = {
attributes: {
name: 'STRING',
tags: {
collection: 'tag',
via: 'tagged'
}
}
};
And this is the controller method that tries to associate data:
module.exports = {
addToPatient: function(req, res) {
Patient.findOne({id: req.param('patientId')}).exec(function(err, patient) {
// Queue up a record to be inserted into the join table
patient.tags.add(req.param('tagId'));
// Save the user, creating the new associations in the join table
patient.save(function(err) {});
});
res.send("tag assigned");
}
};
I've inspected the responses at various breaks and everything seems to be passing just fine. The patient is found. The save function shows a tag association in the patient object, but nothing is added in the database. I assume I will see either a join table being created or something in the patient/tag collections to signify an association, but I see nothing. I'm so very confused. If I do an HTTP get, I'm presented with a "tag assigned" response. What am I missing?
Works fine for me, but you're right in the tag and patient collections, you won't see a populated field with the associations. You'll see new join collections that are created that contains the relationships like #sgress454 pointed out.

Create Both Parent/Child Associated Record in Sailsjs

I'm having a hard time trying to figure out if sails/waterline even does this.
(so an adequate answer would simply be if this is possible or not, I have been reading docs, looking through github issues and looking through code, but still not sure)
I have a one to one association setup where an 'account' has a 'contact'
I'm trying to create a contact within sails blueprints (so basically just using the create() method)
account =
{ name: 'Corp'
contact:{
firstName: 'Bob',
lastName: 'Jones'
}
}
so should Account.create(account).exec() create the account and the associated contact? Because I'm getting the following error
TypeError: Cannot convert null to object
My model is setup like so
account.js
module.exports = {
migrate: 'safe',
tableName: 'accounts',
autoPK: false,
attributes: {
id: {
type: 'INTEGER',
primaryKey: true,
autoIncrement: true
},
contactId: 'INTEGER',
name: {type: 'STRING', maxLength: 100},
contact: {
model: 'contact',
columnName:'contactId'
}
}
};
I'm using sails 10.0-rc8 / waterline 10.0-rc15
Creating an associated instance at the same time as its parent (aka "nested create") should work, but it's tricky to get things just right when you're dealing with a legacy database. In your case, the contactId attribute declaration is probably causing the issue, since Waterline expects the foreign key field to be implicit, not explicit. Try removing:
contactId: 'INTEGER',
entirely and see where that gets you.
After some research I found out that as of version 0.10.0-rc15 of waterline you can NOT have a customized foreign keys. In the above model if I change the "contactId" column to just "contact" (basically make it look exactly like it does in the docs. Then it works.
I made the following bug report
https://github.com/balderdashy/waterline/issues/529