User.findOne acting as User.Update in SailsJs - javascript

I'm requesting the blueprint route User.findOne in SailsJs on the basis of user Id but it itself is calling User.update. Also, I just experienced a new thing that on sending multiple parameters to findOne, it updates the record on the basis of any single matched parameter. On the other hand, If i do create a controller named user.findOne and call the same route via controller, it works perfectly fine.
Is that the right behavior by SailsJs or I'm doing some mistake anywhere?

I have the same issue, still wondering why is this happening,
I even tried creating an update function in my controller with some sample code but when I try hitting findOne from postman, it redirects me to my created update function.
Waiting for an answer on this serious issue.
However I found a solution by trying something like this (i.e. creating custom findOne function in the controller) and it worked:
findOne : function (req,res){
var myReq = req.params.all();
console.log(myReq);
User.findOne(myReq, function UserFound(err, user){
if (err) return res.negotiate("User not found!");
else{
console.log("I am getting here");
console.log(user);
return res.status(200).send(user);
}
})
}

Related

Javascript, where does your 'magic' data come from?

Coming from the Java Programming Language where all information that can be used in a method must either be part of a class, or passed by parameter, I'm very confused on to where JavaScript magically generates it's very important data.
In this case I'm using Socket.IO and trying to call a login-method after connection, now I could just use an anonymous function, but I personally believe they're really ugly.
Here's my code:
socketIO.sockets.on('connection', function(socket) {
console.log("Connection maid.");
socket.on('login', login);
});
function login(json) {
sqlConnection.query('select * FROM Accounts', function(err, rows, fields) {
if(err) throw err;
for(var row in rows) {
if(rows[row].Username == json.username) {
console.log("Exists");
socket.emit('login', {nuel: ''});
}
}
});
}
As you can see the login function is called whenever the socket receives a login message, and the json object is magically passed to it. I have no idea where it comes from or what generates it, nor do I have a clue how to pass additional arguments to the method, because it breaks/overwrites the magic data.
The error I'm running into is where socket doesn't exist in the current context, because it was not passed to the login function, however when I try to pass it, the object saved as json is completely eradicated from existence.... AND WHERE IS THE DATA THAT'S HERE COMING FROM.
I don't understand this at all, How can I pass this information to call the method, without completely breaking everything.

Alternative for Javascript this object

I have a simple function which routes a HTTP query pattern, queries redis and sends a response. The following is the code
router.get('/getinfo/:teamname', function main(teamname) {
rclient.hgetall(teamname,function(err,obj){
console.log("the response from redis is ",obj)
cache.put(eventname,obj);
console.log("inserting to cache");
this.res.end(obj); // this object is root cause for all problems
});
}
The router object afaik, sends the response using this.res.end(obj) . I guess since I am trying to do this inside my redis client , I am getting error. Is there any other way to send the value as a response ? I thought of using emitter based model where the channel emits the response and listener gets it. but it feels like a round about way to solving this problem. Is there any simpler approach ?
The error may be because, where you're trying to use this, it doesn't have the intended value -- an object with a res property that in turn has an end() method.
That would be because every function in JavaScript has its own this with its own value. And, when nesting functions, using this will return the value for the closest function (i.e. shadowing).
To resolve that, you can save the intended value to a local variable:
router.get('/getinfo/:teamname', function main(teamname) {
var request = this;
rclient.hgetall(teamname,function(err,obj){
// ...
request.res.end(obj);
});
});
Or, bind the anonymous callback so both functions are forced to have the same this value:
router.get('/getinfo/:teamname', function main(teamname) {
rclient.hgetall(teamname, function(err,obj){
// ...
this.res.end(obj);
}.bind(this));
});

Meaning of callback parameters in node.js code

I'm very new to Node.js and I'm just trying to make sense of how the parameters work in the callback methods of the code.
I can only understand the first one, function(req,res), because I've used that in Java when working server-side, but I don't really understand how it automatically calls the memcached function or how that kicks off the rest, etc. If somebody could explain to me how this works I'd really appreciate it. Thank you
server.on('request', function(req, res) {
//get session information from memcached
memcached.getSession(req, function(session) {
//get information from db
db.get(session.user, function(userData) {
//some other web service call
ws.get(req, function(wsData) {
//render page
page = pageRender(req, session, userData, wsData);
//output the response
res.write(page);
});
});
});
});
It could roughly be compared to passing the anonymous class in Java. For example to sort a collection in Java you pass a comparator class which has a method for comparing two objects. Later, when sorting algorithms needs to compare the objects it calls the function in provided class.
In javascript functions are first class objects, which means we don't need a "wrapper" class and can pass it as a parameter to another function.
In your case "memcached.getSession" will execute is't logic, find the session, and calls the anonymous function you pass in the second parameter, with the session as parameter.

Calling super method in sails.js controller

When I create a controller in sails.js with some standard method redefined, how do I call default parent method of this controller?
module.exports = {
create: function(req, res) {
//test some parameters
if (condition) {
//call regular super method, proceed as usual
//_super(); <- how to do this?
} else {
//do some other things
}
}
};
Update: for Sails >= v0.10.x, see the comment below from #naor-biton
If you want to access the default implementation (the blueprint), as of v0.9.3, you can call next() (the third argument to your controller). This is because Sails is based on the Express/Connect concept of middleware, allowing you to chain things together.
Please note that this behavior may change in a subsequent version, since next() is also how you call your default 404 handler (config/404.js) for actions which don't have a blueprint underneath them.
A better approach, if you're interested in using the blueprints but running a bit of logic beforehand, is to leave the controller action undefined and use one or more policies, which will be run beforehand.

MVC3 controller action programmatically return a failed post request

I have an Ajax form that sends input data to a controller. I currently have an action result that returns the view and the ajax form helper has an 'OnSuccess' function it calls.
What I would like to do is that if the validation done in the controller fails, then have the POST return as a failure so I can use the OnFailure attribute in the AJAX helper to kickoff another function. Is this possible?
Also, I would prefer not to use Model Binding/validation that way since the Models I use are complex and do not lend themselves easily to binding.
As far as I recall (only just returning to the Ajax helpers), OnFailure is called on an HTTP Status Error, so if you make your view trigger one of those, the OnFailure function should be called, maybe something like the following in the action (going against the idea of exceptions being exceptional, and using an unorthodox status code (Conflict), but you get the idea):
throw new HttpException(409, "Validation error");
Or, using the built in HttpStatusCodeResult:
return new HttpStatusCodeResult(409, "Validation error");
Or, if you need to also return some actual content:
Response.StatusCode = 409;
Response.StatusDescription = "Validation error";
return WhateverResult();
Finally, if you use option 3 a lot, you could create a new ActionResult (or ViewResult) subclass to handle setting the status code and returning the result.

Categories