I have been working with Parse Cloud Code, and I have not achieved setting default values for my classes. Right now I am doing this:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success();
});
When I upload this function to the Cloud Code, and try to create a new object from the dashboard it wont have the default value active = false.
I don't know what's going on. Has somebody achieved this before?
My code is very similar to the one in the Parse docs. They say this could be done like this:
Parse.Cloud.beforeSave("Review", function(request, response) {
var comment = request.object.get("comment");
if (comment.length > 140) {
// Truncate and add a ...
request.object.set("comment", comment.substring(0, 137) + "...");
}
response.success();
});
However, for me it doesn't want to work.
Wohoo! I did it!
Nowhere in the documentation is said that if you want to do so, you must return the object you edited in the response.success().
Solution:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success(request.object); //this is the line that changes
});
Related
Hey I am making a website which as a partial search form. Reference from:https://www.youtube.com/watch?v=ZC2aRON3fWw&t=42s But I couldnt understand why it doesnt work. I use pug instead of hbs.
And these are my codes:
app.get('/sonuc', function(req, res, next){
var q = req.query.q;
Article.find({
title : {
$regex: new RegExp(q)
}
}, {
_id:0,
__v:0
}, function(err, data){
res.render('sonuc', {data:data})
}).limit(10);
});
});
Then this is my layout pug:
.ui-widget
form.form-inline.my-2.my-lg-0
input.form-control.mr-sm-2(type='text', onkeyup='showResults(this.value)', placeholder='Search',action='/article/'+sorgu, aria-label='Search')
button.btn.btn-secondary.my-2.my-sm-0(type='submit')
#search-results(style='width:60px;top:-1px;position:relative')
In this layout pug I thing the onkeyup issue is not working. How can I implement that fu nction on that form?
And ths is my main.js whihc takes query from database and write it in html form:
var showResults = debounce(function(arg){
var value = arg.trim();
if(value == "" || value.length <= o){
$("#search-results").fadOut();
return;
}else{
$("#search-results").fadeIn();
};
var jqhr = $.get('/article/' + value, function(data){
})
.done(function(data){
if(data.length == 0){
$("search-resuts").append('<p classs="lead text-center mt-2">No Results</p>');
}else{
data.forEach(x => {
$("search-resuts").append('<p class="m-2 lead"><img style="width:60px;" src="images/supreme1.jpg">' + x.title +'</p>');
});
}
})
.fail(function(err){
console.log(err);
})
}); 200;
function debounce(func, wait, immediate){
var timeout;
return function(){
var context = this;
args = arguments;
var later = function(){
timeout= null;
if(!immediate)func.apply(context,args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if(callNow)func.apply(context,args);
};
};
I cannot understand these issues and why it doesnt work.As a summary, I want to make a search engine which works with regex and mongodb. İt will be partial that is shown in that youtoube video which is on the above of my article that I referenced. But the real issue is, I couldnt understand the code block of function showResults and I dont know how to translate this codes to my project. So that I am waiting your help. I cannot upload a video to this website so that if you can give me your facebook, instagram or email account I can send the issue which should be solved. I need your help. I have been making this project for a long time for my school but I cannot move on. Please I need your help.
I hope I could express myself well and your helps will solve it.
Yes I got it know. I have made lots of changes instead of using this code blockes.
I wathced : https://www.youtube.com/watch?v=9_lKMTXVk64
And also I documented : Fuzzy Searching with Mongodb?
These two documentations help me a lot. So that my code is almost approximately 90% same as shown in these documentations.
This is my app.js :
app.get('/sonuc', function(req, res){
if (req.query.search) {
const regex = new RegExp(escapeRegex(req.query.search), 'gi');
Article.find({ "title": regex }, function(err, articles) {
if(err) {
console.log(err);
} else {
res.render("index", {
articles: articles
});
}
});
}
});
This is my index.pug file :
extends layout
block content
body
br
br
br
ul.list-group
each article, i in articles
li.list-group-item
a(href="/article/" + article._id)= article.title
And this is my layout.pug file(But I will consider the text form)
form.form-inline.my-2.my-lg-0(action="/sonuc" method="GET")
input.form-control.mr-sm-2(type='text', name,="search", onkeyup='showResults(this.value)', placeholder='Search',action='/article/'+sorgu, aria-label='Search')
button.btn.btn-secondary.my-2.my-sm-0(type='submit')
Please look at:
https://github.com/nax3t/fuzzy-search
Because in my solution I didnt add the message that is applied when we cannot find the word. Or when there is no such a word which is searched by user. The noMatch query.
But after I will apply it to my project I will add it to here.
I was a PHP developer, I'm trying to write code using node.js for praticing. M am confuse about node.js when I execute my program, line of code jump to next line.
This is the part of my code:
//article.js
var article_model = require('../models/article_model');
var comment_model = require('../models/comment_model');
var list_article,list_comment;
app.set('views','./views/article/');
app.set('view engine','ejs');
app.get('/list_article',csrfProtection,function(req,res){
master_model.get_article(req,xparams,function(status,result,total_data){
list_article = result.data;
});
console.log(list_article);
master_model.get_comment(req,xparams,function(status,result,total_data){
list_comment = result.data;
});
console.log(list_comment);
var params = {
title : "Article List",
data_article : list_article,
};
res.render('content.ejs',params);
});
and then
//master_model.js
exports.get_article = function (req,hash, fn) {
var auths = {
user : api_server["auth_username"],
pass : api_server["auth_password"],
}
request.get({url:"http://myapi.com/article/latest", auth:auths } , function(err,httpResponse,body) {
if (!err && httpResponse.statusCode == 200) {
var temp = JSON.parse(body);
if (temp.status == 1){
result_data = {status:1, message : temp.message ,data : temp.data};
return fn(true,result_data,1);
}else if(temp.status == 0){
result_data ={ status:0, message : temp.message};
return fn(false,result_data,0);
}
}else{
result_data ={ status:0, message : "error, please try again"};
return fn(false,result_data,0); //something problem to API
}
})
};
exports.get_comment = function (req,hash, fn) {
var auths = {
user : api_server["auth_username"],
pass : api_server["auth_password"],
}
request.get({url:"http://myapi.com/comment/latest", auth:auths } , function(err,httpResponse,body) {
if (!err && httpResponse.statusCode == 200) {
var temp = JSON.parse(body);
if (temp.status == 1){
result_data = {status:1, message : temp.message ,data : temp.data};
return fn(true,result_data,1);
}else if(temp.status == 0){
result_data ={ status:0, message : temp.message};
return fn(false,result_data,0);
}
}else{
result_data ={ status:0, message : "error, please try again"};
return fn(false,result_data,0); //something problem to API
}
})
};
when i run my code, and open browser, output data is blank, when i refresh again my browser show ouput my data (artcile list, and commment list)
and i look my console if first run
output : {
id : 1
title : title 1..
...
..
}
undefined
If i refresh my browser again, all output complete to show (not show undefined)
My question:
How to make my code run the process step by step until the process end and deliver to views?
Any problem with my code?
Thanks!
To address your initial question properly, you can actually go step by step, using breakpoints. In the latest node 7 and now 6 you can use Chrome Dev Tools to debug a node application. You need to set some breakpoints and watch variables to help you understand:
execution order
the precise values of variables at key moments
I still think breaking the big program into smaller programmes would be helpful and reduce surprises, but learning to debug properly is also really useful!
You just run the program with node --inspect index.js, and then a link will be displayed on the console that you load up in Google Chrome Browser.
There is a more thorough guide, which might help.
The official documentation is also worth a read.
i feel a bit embarrassed, can you please kindly explain parts of the code?
For example, I have no idea, what is this part? where can I read more about it?
function parsePostStory(data) {
return {
name : data.name
}
}
What is req.body? Is it json req body?
Why do we declare empty array and why do we return it? Just for the clarity?
Is Story.create just a mongoose method?
The rest of the code is here:
router.post('/stories', function(req, res) {
var validation = validatePostStory(req.body);
if(validation.length > 0) {
return res.badRequestError(validation);
}
var story = parsePostStory(req.body);
Story.create(story, function(err, story) {
if(err) {
console.log(err.message);
return res.internalServerError();
} res.send(story);
});
});
function validatePostStory(data) {
var array = [];
if (!data.name || typeof data.name !== 'String') {
return array.push('name');
}
return array;
}
function parsePostStory(data) {
return {
name : data.name
}
}
Sorry once more for that kind of a question and thanks a ton.
I'm assuming you know how the request-response cycle works with HTTP requests and the client-server interactions with it. If not, Wikipedia Request-Response and Client-Server (Two link limit, otherwise I would have posted them as links)
A request sends a lot of information to the server. If you console.log the request in NodeJS, you will see that it contains a lot of information that isn't entirely relevant to what you need.
You're using Express as your web framework. In this case, req.body is the information that you are sending to the server from the client. Using req.body will make sure that you're not using the extra information passed in to the server from the client. Req.body is your code that you want. (Note: Req.body isn't natively supported by Express v4, you'll have to use something like body-parser) See Express docs for more details
Now, let's break up this code a bit. You essentially have 3 separate functions. Let's take a look at validatePostStory.
function validatePostStory(data) {
var array = [];
if (!data.name || typeof data.name !== 'String') {
return array.push('name');
}
return array;
}
This function is a validation function. It takes one argument - an object and returns an array. Effectively, what this is doing is checking if the name is a string or not - if not, return an array that has a length of 1. The following conditional checks length and returns a 400 if greater than 0
if(validation.length > 0) {
return res.badRequestError(validation);
}
I'm not entirely sure why this needs to be a separate function. Looks like you can probably just do this instead.
if (!req.body.name || typeof req.body.name !== 'String') {
return res.badRequestError(validation);
}
The following function function essentially converts the data so that mongodb/mongoose can store it in the proper format
function parsePostStory(data) {
return {
name : data.name
}
}
It's the same as saying:
var story = {name: req.body.name}
I would assume Story.create is a custom mongoose method yes.
I'm trying to set params for routing in my webapp by string:
app.param('id', /^\d+$/);
I need it to do for better routing setting, like
app.get('/post/:id', show);
But I'm getting next error:
throw new error ('invalid param() call for ' + name + ', got ' + fn)
What am I doing wrong?
From your comments, it seems evident that you forgot to include the part of the example code which allows support for Regular Expressions in app.param. The documentation has the following code before app.param('id', /^\d+$/);:
app.param(function(name, fn){
if (fn instanceof RegExp) {
return function(req, res, next, val){
var captures;
if (captures = fn.exec(String(val))) {
req.params[name] = captures;
next();
} else {
next('route');
}
}
}
});
Include that, and you should be fine.
Alternatively, you could just use the express-params module, that includes that code for you.
I need to allow the user of my app to download a file with Meteor. Currently what I do is when the user requests to download a file I enter into a "fileRequests" collection in Mongo a document with the file location and a timestamp of the request and return the ID of the newly created request. When the client gets the new ID it imediately goes to mydomain.com/uploads/:id. I then use something like this to intercept the request before Meteor does:
var connect = Npm.require("connect");
var Fiber = Npm.require("fibers");
var path = Npm.require('path');
var fs = Npm.require("fs");
var mime = Npm.require("mime");
__meteor_bootstrap__.app
.use(connect.query())
.use(connect.bodyParser()) //I add this for file-uploading
.use(function (req, res, next) {
Fiber(function() {
if(req.method == "GET") {
// get the id here, and stream the file using fs.createReadStream();
}
next();
}).run();
});
I check to make sure the file request was made less than 5 seconds ago, and I immediately delete the request document after I've queried it.
This works, and is secure(enough) I think. No one can make a request without being logged in and 5 seconds is a pretty small window for someone to be able to highjack the created request URL but I just don't feel right with my solution. It feels dirty!
So I attempted to use Meteor-Router to accomplish the same thing. That way I can check if they're logged in correctly without doing the 5 second open to the world trickery.
So here's the code I wrote for that:
Meteor.Router.add('/uploads/:id', function(id) {
var path = Npm.require('path');
var fs = Npm.require("fs");
var mime = Npm.require("mime");
var res = this.response;
var file = FileSystem.findOne({ _id: id });
if(typeof file !== "undefined") {
var filename = path.basename(file.filePath);
var filePath = '/var/MeteorDMS/uploads/' + filename;
var stat = fs.statSync(filePath);
res.setHeader('Content-Disposition', 'attachment; filename=' + filename);
res.setHeader('Content-Type', mime.lookup(filePath));
res.setHeader('Content-Length', stat.size);
var filestream = fs.createReadStream(filePath);
filestream.pipe(res);
return;
}
});
This looks great, fits right in with the rest of the code and is easy to read, no hacking involved, BUT! It doesn't work! The browser spins and spins and never quite knows what to do. I have ZERO error messages coming up. I can keep using the app on other tabs. I don't know what it's doing, it never stops "loading". If I restart the server, I get a 0 byte file with all the correct headers, but I don't get the data.
Any help is greatly appreciated!!
EDIT:
After digging around a bit more, I noticed that trying to turn the response object into a JSON object results in a circular structure error.
Now the interesting thing about this is that when I listen to the filestream for the "data" event, and attempt to stringify the response object I don't get that error. But if I attempt to do the same thing in my first solution(listen to "data" and stringify the response) I get the error again.
So using the Meteor-Router solution something is happening to the response object. I also noticed that on the "data" event response.finished is flagged as true.
filestream.on('data', function(data) {
fs.writeFile('/var/MeteorDMS/afterData', JSON.stringify(res));
});
The Meteor router installs a middleware to do the routing. All Connect middleware either MUST call next() (exactly once) to indicate that the response is not yet settled or MUST settle the response by calling res.end() or by piping to the response. It is not allowed to do both.
I studied the source code of the middleware (see below). We see that we can return false to tell the middleware to call next(). This means we declare that this route did not settle the response and we would like to let other middleware do their work.
Or we can return a template name, a text, an array [status, text] or an array [status, headers, text], and the middleware will settle the response on our behalf by calling res.end() using the data we returned.
However, by piping to the response, we already settled the response. The Meteor router should not call next() nor res.end().
We solved the problem by forking the Meteor router and making a small change. We replaced the else in line 87 (after if (output === false)) by:
else if (typeof(output)!="undefined") {
See the commit with sha 8d8fc23d9c in my fork.
This way return; in the route method will tell the router to do nothing. Of course you already settled the response by piping to it.
Source code of the middleware as in the commit with sha f910a090ae:
// hook up the serving
__meteor_bootstrap__.app
.use(connect.query()) // <- XXX: we can probably assume accounts did this
.use(this._config.requestParser(this._config.bodyParser))
.use(function(req, res, next) {
// need to wrap in a fiber in case they do something async
// (e.g. in the database)
if(typeof(Fiber)=="undefined") Fiber = Npm.require('fibers');
Fiber(function() {
var output = Meteor.Router.match(req, res);
if (output === false) {
return next();
} else {
// parse out the various type of response we can have
// array can be
// [content], [status, content], [status, headers, content]
if (_.isArray(output)) {
// copy the array so we aren't actually modifying it!
output = output.slice(0);
if (output.length === 3) {
var headers = output.splice(1, 1)[0];
_.each(headers, function(value, key) {
res.setHeader(key, value);
});
}
if (output.length === 2) {
res.statusCode = output.shift();
}
output = output[0];
}
if (_.isNumber(output)) {
res.statusCode = output;
output = '';
}
return res.end(output);
}
}).run();
});