Insert new collection after function runs on server - meteor

When I return the geocode from googles API I'm trying to save it into my database. I've been trying to use the code below, to just insert a Test document with no luck. I think it has something to do with meteor being asynchronous. If I run the insert function before the googleMapsClient.geocode function it works fine. Can someone show me what I'm doing wrong.
Meteor.methods({
'myTestFunction'() {
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Test.insert({test: 'test name'});
}
});
}
});

I see now where you got the idea to run the NPM library on the client side, but this is not what you really want here. You should be getting some errors on the server side of your meteor instance when you run the initial piece of code you gave us here. The problem is that the google npm library runs in it's own thread, this prevents us from using Meteor's methods. The easiest thing you could do is wrap the function with Meteor.wrapAsync so it would look something like this.
try {
var wrappedGeocode = Meteor.wrapAsync(googleMapsClient.geocode);
var results = wrappedGeocode({ address : "testAddress" });
console.log("results ", results);
Test.insert({ test : results });
} catch (err) {
throw new Meteor.Error('error code', 'error message');
}
You can find more info by looking at this thread, there are others dealing with the same issue as well

You should run the googleMapsClient.geocode() function on the client side, and the Test.insert() function on the server side (via a method). Try this:
Server side
Meteor.methods({
'insertIntoTest'(json) {
Test.insert({results: json.results});
}
});
Client side
googleMapsClient.geocode({
address: 'test address'
}, function(err, response) {
if (!err) {
Meteor.call('insertIntoTest', response.json);
}
});

Meteor Methods should be available on the both the server and client sides. Therefore make sure that your method is accessible by server; via proper importing on /server/main.js or proper folder structuring.
(If a method contains a secret logic run on the server, it should be isolated from the method runs on both server & client, though)

Related

Meteor.userId() not available in ConnectHandlers

I am trying to create a file upload feature in Meteor where a logged in user is able to upload a file to the server under a directory named after their username. I have the basics working but when I take it a step further by checking the logged in user ID, things start breaking. Specifically:
WebApp.connectHandlers.use('/upload/', function(req, res) {
if (this.userId) {
// Do cool stuff.
} else {
res.writeHead(500, {"content-type":"text/html"});
res.end("this.userId = " + this.userId); // End the response.
}
});
Result:
this.userId = undefined
And...
WebApp.connectHandlers.use('/upload/', function(req, res) {
if (Meteor.userId()) {
// Do cool stuff.
} else {
res.writeHead(500, {"content-type":"text/html"});
res.end("Meteor.userId() = " + Meteor.userId()); // End the response.
}
});
Result:
Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.
at Object.Meteor.userId (packages/accounts-base/accounts_server.js:19:1)
at Object.Package [as handle] (packages/cool_package/upload.js:34:1)
at next (/Users/me/.meteor/packages/webapp/.1.2.0.19shc3d++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:190:15)
at Function.app.handle (/Users/me/.meteor/packages/webapp/.1.2.0.19shc3d++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:198:3)
at Object.fn [as handle] (/Users/me/.meteor/packages/webapp/.1.2.0.19shc3d++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:74:14)
at next (/Users/me/.meteor/packages/webapp/.1.2.0.19shc3d++os+web.browser+web.cordova/npm/node_modules/connect/lib/proto.js:190:15)
at Object.WebAppInternals.staticFilesMiddleware (packages/webapp/webapp_server.js:331:1)
at packages/webapp/webapp_server.js:625:1
The code above is included in a Meteor package I'm developing. The package.js file specifies that the code should run on the server:
api.add_files("upload.js", "server");
So my questions are:
What is the correct way to check the logged in user ID and username?
Can this code be moved to an Iron Router route instead?
It looks like the line
WebApp.connectHandlers.use('/upload/', function(req, res) {
Is Express.js or similar code -- if so, you have broken out of the Meteor frameowrk providing your own REST services etc. If that is the case you also have to provide your own user management and authentication scheme for incoming REST calls, just as you would in any other bare-bones REST applications

Meteor observeChanges removed callback won't execute server methods

I am observing changes on the Results collection on the client and calling methods on the server for the added and removed callbacks. (The following is only on the client and 'foo' is on the server.)
Results.find().observeChanges({
added: function (id, doc) {
console.log('added on client')
Meteor.call('foo')
},
removed: function (id) {
console.log('removed on client')
Meteor.call('foo')
}
})
Here is the server code.
Meteor.methods({
foo: function() {
console.log('server code run')
}
})
If I insert a document on the client I get 'added on client' on the client and 'server code run' on the server. If I remove a document on the client, I get 'removed on the client' on the client, but nothing on the server at all.
Does anyone know what is going on?
A few suggestions:
Does the code run on the server (e.g if you put it into a Tracker.autorun block)?
Are there any errors on the server console?
Is there any error on the browser console?
If other code within the removed callback gets executed, the server method call will be executed too. There are no restrictions for these callbacks. I don't think your problem is with the code you've pasted. Maybe add the server method code as well.

meteor.call does not call method from meteor.method

i have an issue with callback method.
i have created on methods.js in server folder
and one callback.js file in client/test/mytest folder.
my callback.js contains following code
Template.testHello.events({
"click #testHello": function(e) {
Meteor.call("testmethod",function(error, id) {
if (error) {
Errors.throwError(error.reason);
}
return false;
});
return false;
}
});
and methods.js file code is
Meteor.methods({
testmethod: function(att) {
alert("hello testmethod..");
}
});
but when i clicked on button "testHello" then it gives me error like "internal server error 500".
can anyone have idea about this?
Thanks,
It makes no sense to have client-only method calls because Meteor methods are intended to perform RMI (remote method invokation) on the server.
Move your methods.js to either server/methods.js or lib/methods.js if you want your method to have a simulation counterpart on the client.
EDIT :
As hinted by #user728291, the alert method is defined on the window object which is a browser related object thus only available on client environment, you can use console.log instead to print something on the server.

Writing an async test with Intern

I am trying to write an Integration test which calls my real service (that returns JSON) and makes sure the format of the JSON is OK.
I get an error
Error: Unable to load http://localhost:7200/users/signoff status: 0
ErrorCtor#http://localhost:9000/resources/www/tests/lib/dojo/errors/create.js:29
onError#http://localhost:9000/resources/www/tests/lib/dojo/request/xhr.js:133
I've got a service that has the actual functions to interact with the server and it returns promises from every function. My test looks like this.
define([
'intern!bdd',
'intern/chai!expect',
'app/services/myService'
], function (bdd, expect, MyService) {
with (bdd) {
describe('Service Tests', function () {
var service;
before(function () {
service = MyService.getInstance();
});
it('should sign user off', function(){
var dfd = this.async(2000);
service.signUserOff().then(dfd.callback(function (data) {
expect(data).to.exist;
expect(data.status).to.exist;
}), dfd.reject.bind(dfd));
});
});
}
});
service.signOff() makes a call to the real service and then returns a promise. I have tried this with Firefox and PhantomJS both and I keep getting this error. The weird thing is, the URL in the error works fine if loaded manually in the browser.
I wonder if this is something to do with Intern not being able to load the request/xhr.js and therefore throwing this error?
The request that you are making is considered a cross-site request, so you need to either make sure your server correctly responds with the appropriate CORS headers for such a request, or you need to set up a reverse proxy that ensures that the XHR requests are occurring through the same origin.

Using tinytest to test Meteor client while the server is running

Is it possible to test the Meteor client while the server is running using tinytest? Here's my example testing the client only:
Tinytest.add("Add object to a collection", function(test) {
var people = new Meteor.Collection("people");
people.insert({"name": "Andrew"}, function(error, id) {
test.isNull(error);
});
});
For a fraction of a second this passes, but then it goes into the state of "waiting". I'm also positive that error is not null.
Meteor.Error {error: 404, reason: "Method not found", details: undefined}
I know this is happening because their is no server for the client to communicate with. When I try to run this test on the server and client, I continue to get the same issue with the client. Is there a way to test the client while the server is running?
Thanks, Andrew
Use new Meteor.Collection with no argument to create a stub collection that doesn't require the server. See the docs on Collections:
If you pass null as the name, then you're creating a local collection. It's not synchronized anywhere; it's just a local scratchpad that supports Mongo-style find, insert, update, and remove operations.
This is an async test, so you'll have to use addAsync.
Tinytest.addAsync("Add object to a collection", function(test, next) {
var people = new Meteor.Collection("people");
people.insert({"name": "Andrew"}, function(error, id) {
test.isNull(error);
next();
});
});
Note the next argument which signals that you are done in the callback.

Resources