I have been using Meteor for two weeks, I am trying to add functionality to send an email once the user account has been created. I have looked at several tutorials on the Accounts.onCreateUser() function. Here is the code below.
if(Meteor.isClient{
....some code here.....
Accounts.createUser({
..... Insert some options ......
}, function(error){
..... some More code here ......
});
}
if(Meteor.isServer){
Accounts.onCreate(function(options, user){
...... Do the required .......
});
}
It seems like it is according to the several tutorials that I have been using.
I have tested out the code and but the onCreate for the account is always returning 'Internal server error' and I can't find out a cause for it. Is this the way that I am supposed the Accounts.onCreate() callback for the form?
Also is there a debugging functionality if so I can further track the code down?
Thanks
Your code says onCreate instead of onCreateUser. Maybe that's a typo? Also make sure it is returning a user document. You can always add a console.log to test if the function is being called with the right parameters.
Related
I have a document in an array and try to update a value in the document.
It is already working in Meteor's Mongo shell:
$ meteor mongo
meteor:PRIMARY> db.mycollection.update({name:"test", "foo.name":"bar"}, {$set: {"foo.$.price":42}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
But t's not working when I try to do it in Meteor with:
MyCollection.update(
{name:"test", "foo.name":"bar"},
{$set: {"foo.$.price":42}}
);
As you can see here: http://meteorpad.com/pad/jjazD3jYYeY7R9Bpv/DocumentArrayUpdate
This is caused because you cannot put a selector different than the Id on the client side (with autopublish/insecure):
Error: Not permitted. Untrusted code may only update documents by ID. [403]
This is where I'm lost. I have to run this update code on the server but the only examples I've seen so far are only doing some .find() or .findOne() on the server's Meteor.publish() and then all the update logic is done in Meteor.methods() which is client and server side, so in my case I cannot do that.
How can I make this work?
Edit: I've been little bit fast saying that: Meteor.methods() is both client and server side, so in my case I cannot do that. It actually works well with Meteor.methods(), I still don't know why, I think it's coming from how Meteor's Optimistic UI feature works...
Error: Not permitted. Untrusted code may only update documents by ID. [403]
This means you've removed the insecure package, which is a good thing for production. But what that means is you can no longer update your database entries from the client unless you update by the collection's ID (as the error states.
So you have two options.
First - the bad option. From the client:
MyCollection.update(
{_id:"19283yhakjsdo23", "foo.name":"bar"},
{$set: {"foo.$.price":42}}
);
It's not terribly bad, but it's not good either.
The good option: from the server.
Meteor has something called server side methods (a good blog post about this is available). Server side methods are great and will allow you to do exactly what you want to do with almost the exact same code, but from the server.
So in a file called methods.js from your server directory you would write:
Meteor.methods({
priceUpdateMethod(name, collectionkey, updateValue) {
MyCollection.update(
{name:name, "foo.name":"bar"},
{$set: {collectionkey: updateValue}}
);
}
});
Then in your client directory you'll have a helper or something like that with a function:
Meteor.call('priceUpdateMethod',"test","foo.$.price",42)
Server is trusted. Client is untrusted.
Change your meteor method to this:
if (Meteor.isServer()) {
MyCollection.update(
{name:"test", "foo.name":"bar"},
{$set: {"foo.$.price":42}}
);
}
if (Meteor.isClient()) {
_id = MyCollection.findOne(
{name:"test", "foo.name":"bar"}
)._id;
MyCollection.update(_id, {$set: {"foo.$.price":42}});
}
As David mentioned in the comments your code will work on the server. To enable it to work on the client as well (latency compression), try this approach.
I have thig angularJS frontend and I use express, node and mongo on the backend.
My situation looks like:
//my data to push on server
$scope.things = [{title:"title", other proprieties}, {title:"title", other proprieties}, {title:"title", other proprieties}]
$scope.update = function() {
$scope.things.forEach(function(t) {
Thing.create({
title: t.title,
//other values here
}, function() {
console.log('Thing added');
})
})
};
//where Thing.create its just an $http.post factory
The HTML part looks like:
//html part
<button ng-click="update()">Update Thing</button>
Then on the same page the user has the ability to change the $scope.things and my problem is that when I call update() again all the things are posted twice because literally thats what I'm doing.
Can someone explain me how to check if the 'thing' its already posted to the server just to update the values ($http.put) and if its not posted on server to $http.post.
Or maybe its other way to do this?
I see a few decisions to be made:
1) Should you send the request after the user clicks the "Update" button (like you're currently doing)? Or should you send the request when the user changes the Thing (using ngChange)?
2) If going with the button approach for (1), should you send a request for each Thing (like you're currently doing), or should you first check to see if the Thing has been updated/newly created on the front end.
3) How can you deal with the fact that some Thing's are newly created and others are simply updated? Multiple routes? If so, then how do you know which route to send the request to? Same route? How?
1
To me, the upside of using the "Update" button seems to be that it's clear to the user how it works. By clicking "Update" (and maybe seeing a flash message afterwards), the user knows (and gets visual feedback) that the Thing's have been updated.
The cost to using the "Update" button is that there might be unnecessary requests being made. Network communication is slow, so if you have a lot of Thing's, having a request being made for each Thing could be notably slow.
Ultimately, this seems to be a UX vs. speed decision to me. It depends on the situation and goals, but personally I'd lean towards the "Update" button.
2
The trade-off here seems to be between code simplicity and performance. The simpler solution would just be to make a request for each Thing regardless of whether it has been updated/newly created (for the Thing's that previously existed and haven't changed, no harm will be done - they simply won't get changed).
The more complex but more performant approach would be to keep track of whether or not a Thing has been updated/newly created. You could add a flag called dirty to Thing's to keep track of this.
When a user clicks to create a new Thing, the new Thing would be given a flag of dirty: true.
When you query to get all things from the database, they all should have dirty: false (whether or not you want to store the dirty property on the database or simply append it on the server/front end is up to you).
When a user changes an existing Thing, the dirty property would be set to true.
Then, using the dirty property you could only make requests for the Thing's that are dirty:
$scope.things.forEach(function(thing) {
if (thing.dirty) {
// make request
}
});
The right solution depends on the specifics of your situation, but I tend to err on the side of code simplicity over performance.
3
If you're using Mongoose, the default behavior is to add an _id field to created documents (it's also the default behavior as MongoDB itself as well). So if you haven't overridden this default behavior, and if you aren't explicitly preventing this _id field from being sent back to the client, it should exist for Thing's that have been previously created, thus allow you to distinguish them from newly created Thing's (because newly created Thing's won't have the _id field).
With this, you can conditionally call create or update like so:
$scope.things.forEach(function(thing) {
if (thing._id) {
Thing.update(thing._id, thing);
}
else {
Thing.create(thing);
}
});
Alternatively, you could use a single route that performs "create or update" for you. You can do this by setting { upsert: true } in your update call.
In general, upsert will check to see if a document matches the query criteria... if there's a match, it updates it, if not, it creates it. In your situation, you could probably use upsert in the context of Mongoose's findByIdAndUpdate like so:
Thing.findByIdAndUpdate(id, newThing, { upsert: true }, function(err, doc) {
...
});
See this SO post.
#Adam Zemer neatly addressed concerns I raised in a comment, however I disagree on some points.
Firstly, to answer the question of having an update button or not, you have to ask yourself. Is there any reason why the user would like to discard his changes and not save the work he did. If the answer is no, then it is clear to me that the update should not be place and here is why.
To avoid your user from loosing his work you would need to add confirmations if he attempts to change the page, or close his browser, etc. On the other if everything is continuously saved he has the peace of mind that his work is always saved and you dont have to implement anything to prevent him from loosing his work.
You reduce his workload, one less click for a task may seem insignificant but he might click it many time be sure to have his work save. Also, if its a recurrent tasks it will definitely improve his experience.
Performance wise and code readability wise, you do small requests and do not have to implement any complicated logic to do so. Simple ng-change on inputs.
To make it clear to him that his work is continuously save you can simply say somewhere all your changes are saved and change this to saving changes... when you make a request. For exemple uses, look at office online or google docs.
Then all you would have to do is use the upsert parameter on your mongoDB query to be able to create and update your things with a single request. Here is how your controller would look.
$scope.update = function(changedThing) { // Using the ng-change you send the thing itself in parammeter
var $scope.saving = true; // To display the saving... message
Thing.update({ // This service call your method that update with upsert
title: changedThing.title,
//other values here
}).then( // If you made an http request, I suppose it returns a promise.
function success() {
$scope.saving = false;
console.log('Thing added');
},
function error() {
//handle errors
})
};
I'm getting the "Error: Trying to open unclosed connection," but I don't believe it's due to a db issue... and that's why I'm stumped. Most solutions to this error, reference db connection issues.
My goal here is execute an external process. If the process closes with anything other than exit code 0, I want to email an alert for example.
I was using the child.on('close', function(code).... to get the exit value from the external process (coming back as "code") So if code !=0 I want to do something... maybe rerun the test... maybe call a different method that sends an email, etc.
Each time I attempt to call a method, from within child.on('close'), I get the error "Trying to open unclosed connection." Which is why I'm also handling the save action in the same block.
Code Sample:
var spawn = require('child_process').spawn,
child = spawn('sipp', ['-s', dnis,server, '-sn', scenario, '-m', '1','-i','127.0.0.1','-recv_timeout','1000']);
}
child.on('close',function(code){
if(code != 0){
Call().emailAlert(dnis, server, scenario, type, carrier);
}
var TestResults = mongoose.model('test_results', TestResultsSchema);
// Saving results to MongoDB
var result = new TestResults({
testType: type,
dnis: dnis,
server: server,
result: code,
carrier: carrier,
date: Date.now()
});
result.save(function (err) {if (!err) {console.log ('Successful Save!')}
else{console.log(err)}});
});
};
If I remove:
if(code != 0){
Call().emailAlert(dnis, server, scenario, type, carrier);
}
The error goes away. What's the best way for me to capture the exit code of the process, and based on it, make a call to a different method (i.e. to email an alert) in Node.js?
I guess I was wrong. I changed the mongoose.connect to mongoose.createConnection and this specific error went away... but unfortunately I'm left with more errors. I'll open up the main question in a different topic.
I used the Graph API with javascript to fetch all of my data contained locations in v1.0.
( I used FB.api("/v1.0/me/locations", function (response) { ... }); )
I know that the updated version is 2.2 and the "locations" node is replaced by "tagged_places" node in v2.0 and above.
I also use the Graph API Explorer to test my results.
I try this, GET: /v2.2/me?fields=tagged_places
and the results are exactly what I want.
However, in my js code, I try: FB.api("/v2.2/me?fields=tagged_places", function (response) { ... });
and there is NO any results!
Besides,
I set version: 'v2.2' in Parse.FacebookUtils.init();
I also ask the permissions :user_tagged_places,user_photos,user_status,user_friends,user_about_me,user_birthday,read_stream in Parse.FacebookUtils.logIn();
I need almost all of the data of my checkins(a.k.a locations in v1.0/tagged_places in v2.0) to add into my database.
I try to fetch /me/photos, but the results are not satisfied. So I still need to use maybe this: FB.api("/v2.2/me?fields=tagged_places", function (response) { ... });
So... can anyone help me? please....
I went through permissions in groups testing them out and I figured out what the problem was.
You need to have the permission of the item you were tagged in.
So in my case I was tagged in photos, so I needed user_photos permission to gain access to user_tagged_places. It actually creates quite an issue because you need to know how a user was tagged to retrieve their tagged_places.
If a user was tagged at a place in a post you need a different permission than if they were tagged in a photo.
I have a problem with http://yuilibrary.com/gallery/show/notify
Unfortunately I'm using the older version of YUI (3.4.0) so it's even harder to search for the solutions. I can't change it so I have to stick to it :(
I have read documentation page a couple of times, but I still can't figure out how to use flag. It says it's a part of configuration of Y.Notify.Message, but how do I access it? There is no example on the site except a very simple way of using Y.Notify constructor.
I was trying something like that:
notification.add({
message : 'Some message',
flag : 'some_flag',
timeout : 1000,
});
Unfortunately it does nothing ...
Any help will be appreciated, because I'm leaning to some 3rd-party library more and more... Still I would rather use something that is part of the framework I use.
The funniest part is I have checked the source code on the github:
https://github.com/yui/yui3-gallery/blob/master/src/gallery-notify/js/notify.js
...and I don't see any flag there :(
However have I found one here:
https://github.com/yui/yui3-gallery/blob/master/src/gallery-notify/js/notify.js~
What is the current version? Anyone?
I also checked the github repository for https://github.com/apipkin/xarno/blob/master/src/gallery-xarno-notify/js/notify.js which should be the most recent version of the code and it also has no flag.
Thanks a million!
It's a bug. You should contact the author.
A workaround to add a class for skinning would be to create the message as a widget first, add your class and then pass it to Y.Notify:
var message = new Y.Notify.Message({
message: 'Some message',
timeout: 1000
});
message.get('boundingBox').addClass('my-skin-class');
notification.add(message);
Another option would be to add it as an object to the notification widget and then retrieve it using item(index):
notification.add({
message: 'Some message',
timeout: 1000
});
notification.item(notification.size() - 1).get('boundingBox').addClass('my-skin-class');