Sails js custom/calculated attributes is not working, using code from sails docs - sails.js

I have this model that is taken from this sails documentation page
module.exports = {
attributes: {
// Primitive attributes
firstName: {
type: 'string',
defaultsTo: ''
},
lastName: {
type: 'string',
defaultsTo: ''
},
// Attribute methods
getFullName: function (){
return this.firstName + ' ' + this.lastName;
}
}
};
What I expect when I call my auto generated restful api (using blueprint)
localhost:port/resourceName
is
{"firstName":"john", "lastName":"Doe", "getFullName": "john Doe"}
instead what I am getting is this
{"firstName":"john", "lastName":"Doe"}
any ideas?
I already checked other posts such as this one github.
sails version: 0.11.4
Thanks a lot :)

If you want the custom attribute to be serialised you can override the default toJSON instance method:
toJSON: function() {
var obj = this.toObject();
obj.fullName = this.getFullName();
return obj;
}

Related

mongoose set a default field to take value of 2 other fields

Is there a way to let one field take value of two other fields merged as default.
I have a user schema as follows:
const UserSchema = mongoose.Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},});
I want to add a third field called fullName that defaults to merging firstName + lastName
Is that possible in mongoose?
try this :
fullName:{
type:String,
required:true,
default: function(){
return this.firstName + " " + this.lastName
}}
on doc update :
yourSchema.pre("updateOne", function (next) {
this.set({ fullName: this.get("firstName") + " " + this.get("lastName") });
next();
});
I solved this using Virtual Setters (Virtuals) as documented by Mongoose
Make sure to add this to your Schema to include virtuals when you convert a document to JSON
const opts = { toJSON: { virtuals: true } };

Virtual field AND real field

Is it possible to have a virtual field that is also a field in a model?
var exampleSchema = new Schema({
name : {type: String, required: true}
slug:: {type: String}
});
exampleSchema.virtual('slug').get(function() {
if(this.slug && this.slug.length){
return this.slug;
}
return this.name.toLowerCase().replace(/ /g, '');
});
If slug is set I want to return the slug. If not, I want to return a computed value from name.
I don't want to use a static method, it needs to be a part of the result when pulled a record.
You can create a custom getter function and return the value if it exists, or the computed value if it doesn't.
var exampleSchema = new Schema({
name: {type: String, required: true}
slug: {
type: String,
get: function(value) {
if (value) {
return value;
} else {
return this.name.toLowerCase().replace(/ /g, '');
}
}
}
});

Global model base url and optional automapping

Is there a way to set a global api_root attribute instead of repeating the declaration over and over in the codebase?
So instead of:
var UserModel = Backbone.Model.extend({
urlRoot: '/user',
defaults: {
name: '',
email: ''
}
});
var user = new UserModel();
user.save(userDetails, {
success: function (user) {
alert(user.toJSON());
}
});
I could have set an app-wide attribute like:
app.api_root = 'https://api.ltmo.com/';
And then just map according to convention:
var UserModel = Backbone.Model.extend({ // maps to https://api.ltmo.com/users/
defaults: {
name: '',
email: ''
}
});
var user = new UserModel();
user.save(userDetails, {
success: function (user) {
alert(user.toJSON());
}
});
you could solve this on the jQuery level with ajaxprefilter:
$.ajaxPrefilter(function(options) {
options.url = 'https://api.ltmo.com/' + options.url;
});

How to use URLs like '/update/:id' as KendoUI datasource?

I read the documentation but found nothing related to setting parameters in dataSource urls. Is it possible to achieve that?
Thx in advance.
Yes, it is possible. The urls defined in the DataSource.transport might be a function. This function receives (for update) as first argument the data being updated (the model) and returns the string that should be used as URL.
Composing the URL for what you want to do is:
var ds = new kendo.data.DataSource({
transport: {
read: {
url: function () {
return 'read';
}
},
update: {
url : function (item) {
return 'update/' + item.id;
}
}
}
});
The answer seems to be vague on 'item.'
Just note that 'item' is an object. In fact anything passed in to read has to be an object, that's what Kendo expects. If you pass anything else into read, like a string, it will convert it into an object which isn't what you want. So, the solution is as follows:
_viewModel: kendo.observable({
items: new kendo.data.DataSource({
transport: {
read: {
url: function (args) {
var urlParm = '?take=' + 1 + '&skip=0&page=1&pageSize=' + 1;
return CGI_ISD._base + 'api/executionsummary/executiondetails/' + args.msgId + urlParm;
},
dataType: "json"
},
},
schema: {
data: function (response) {
return response.AggregateData.Data;
}
}
}),
}),
_reload: function (msgId) {
this._viewModel.items.read({msgId: msgId});
}
Short answer:
Nope.
Long answer:
Parameters are passed either inline with the url parameter of the transport object...
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees?id=' + id
}
}
});
...or they are passed in the data parameter of the transport object.
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees',
data: {
id: id;
}
}
}
});
or
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees',
data: function () {
return { id : id };
}
}
}
});

Can I hook up a model to an existing database?

I have mongodb sitting behind an existing API and want to migrate the API to use sailsjs.
The data structure isn't anything crazy - just standard stuff using default mongodb ObjectIds as primary keys.
Will I be able to use this existing db with sails by just wiring up sails models? Do I need to specify the _id field? And, if so, what datatype should I use?
E.g. Existing mongodb with user collection with the following schema:
_id
name
fname
lname
age
Can I just wire up using something like the following for it to work?:
// User.js
var User = {
attributes: {
name: {
fname: 'STRING',
lname: 'STRING'
},
age: 'INTEGER'
}
};
module.exports = Person;
First: you dont have to define _id (waterline do this for you)
Waterline wants to help you using the same Functions and Models for all types of databases. A "Sub-Field" is not supported in mysql for example. So this don't work.
You can do this:
// User.js
var User = {
attributes: {
name: 'json',
age: 'integer'
}
};
module.exports = User;
If you want to validate "name" you can add your own validation:
// User.js
var User = {
types: {
myname: function(json){
if(typeof json.fname == "string" && typeof json.lname == "string"){
return true;
}else{
return false;
}
}
},
attributes: {
name: {
type: "json",
myname: true
},
age: 'integer'
}
};
module.exports = User;