getting some part of URL - meteor

I'm trying to get the end part of this URL (in the sever side):
http://localhost:3000/insAds/D79htZY8DQ3YmcscE
I mean I want to get this string:
D79htZY8DQ3YmcscE
there is a similar question: How to get the query parameters in Iron-router?
but non of the answers can't help me! because I have no query params in the URL.
I know these codes gives me the string that I want:
this.params.id
and
Router.current().params.id
but these codes works only in client side! I want to get that string in the server side!
finally I'm trying to get that string and use here:
Ads.before.insert(function(userId, doc) {
//console.log(this.params.id);
doc._categoryId = this.params.id;
doc.createdAt = new Date();
doc.createdBy = Meteor.userId();
});

You can use Router.current().params or this.params like this
Router.route('/insAds/:id', function () {
console.log(this.params.id); // this should log D79htZY8DQ3YmcscE in console
});
Check the third example in Quick Start section of iron router documentation
EDIT: Based on our chat,
Your hook is
Ads.before.insert(function(userId, doc) {
//console.log(this.params.id);
doc._categoryId = this.params.id;
doc.createdAt = new Date();
doc.createdBy = Meteor.userId();
});
Change it to
Ads.before.insert(function(userId, doc) {
doc.createdAt = new Date();
doc.createdBy = Meteor.userId();
});
And then define meteor method in server like this
Meteor.methods({
'myInsertMethod': function (id) {
Ads.insert({
_categoryId: id
});
}
});
Call this from client side like this
Meteor.call('myInsertMethod', Router.params().id, function (err, res) {
console.log (err, res);
});

Related

Meteor return response from server method to client

I am trying to integrate a payment API. The method I'm using to create a payment should return an object. And in fact it does, but it's just that I can't get the object back to the client.
I know that this happens because the method to API is executed asynchronously, while method on server is executed synchronously (If I'm not mistaken). But still I can't figure out how to do it, and I am hoping you guys can help me out.
Client side call to server:
Meteor.call('createPaymentLink',NewBooking, TotalAmount ,function(result) {
console.log(result);
});
Server side call to API:
Meteor.methods({
'createPaymentLink': function(bookingID, amount) {
//Create Booking No.
// First two digits = First two digits of booking ID
// Last two digits = Last two digits of Customer ID
var CustomerId = Bookings.findOne({_id: bookingID}).CustomerID;
var FirstPart = CustomerId.substring(0,2);
var LastPart = bookingID.slice(-2);
var rightNow = new Date();
var OrderDate = rightNow.toISOString().slice(0,10).replace(/-/g,"");
var CustomerBookingCode = (FirstPart + OrderDate + LastPart).toUpperCase();
mollieClient.payments.create({
amount: amount,
description: "Booking code: "+bookingID,
redirectUrl: "https://webshop.example.org/order/12345/"
}, Meteor.bindEnvironment(function(payment) {
return payment;
//Bookings.update({_id: bookingID}, {$set: {payment_id : PaymentUrl}});
}));
}
});
The first argument to the callback is the error, which will be null if everything worked! Try this:
Meteor.call('createPaymentLink',NewBooking, TotalAmount ,function(err, result) {
console.log(result);
});

Meteor wrapAsync returning undefined to external service using php connector

I've been stuck on this for way too long. Can anyone help show me why my wrapasync method is returning as "undefined"? I'm trying to make a call to Facebook api and have used a php connector that my meteor app should use to talk to the Facebook PHP SDK. My app talks to the my php file and returns simple functions. But when I actually call the external service it comes back as undefined, although when I run the php function in php it comes out fine and returns expected results. Here's the code, everything is server-side:
var phpAsync = function() {
var execPhp = Meteor.npmRequire('exec-php');
execPhp('C:/xampp/htdocs/xampp/Facebook/file.php', function(error, php, output){
// php now contain user defined php functions.
php.me( function(error, result, output, printed){
// `result` is return value of `my_own_php_function` php function.
console.log(result);
return result;
});
});
};
Meteor.methods({
phpConnect: function () {
var phpSync = Meteor.wrapAsync(phpAsync);
var result = phpSync();
console.log(result);
return result
}
});
The function that is passed in to Meteor.wrapAsync should have callback as the final parameter. From the docs,
Wrap a function that takes a callback function as its final parameter.
The signature of the callback of the wrapped function should be
function(error, result){}
So you should do something like this,
var phpSync = function() {
var execPhp = Meteor.npmRequire('exec-php');
var execPhpSync = Meteor.wrapAsync(execPhp);
var php = execPhpSync('C:/xampp/htdocs/xampp/Facebook/file.php');
php.meSync = Meteor.wrapAsync(php.me);
var result = php.meSync();
console.log(result);
return result;
};
Meteor.methods({
phpConnect: function () {
var result = phpSync();
console.log(result);
return result;
}
});
OR
if you want other stuff like output and printed then you do it like this
var phpAsync = function(cb) {
var execPhp = Meteor.npmRequire('exec-php');
execPhp('C:/xampp/htdocs/xampp/Facebook/file.php', function(error, php, output){
//IMPORTANT: you need to call php.me only if there is no error
// php now contain user defined php functions.
php.me( function(error, result, output, printed){
// `result` is return value of `my_own_php_function` php function.
if (typeof cb === "function) {
cb(error, {
result: result,
output: output,
printed: printed
});
}
});
});
};
Meteor.methods({
phpConnect: function () {
var phpSync = Meteor.wrapAsync(phpAsync);
var result = phpSync();
console.log(result.result, result.output, result.printed);
return result.result;
}
});

In Meteor, how to choose a collection based on a variable?

Let's say you want to dynamically insert into different collections. Right now I am using a switch statement:
switch (i) {
case "dog":
Dog.insert({
name: "Skippy"
});
break;
case "cat":
Cat.insert({
name: "Skippy"
});
break;
}
But this is messy, and if I need to support future collections, it fails. Is there a way to choose the collection based on "i" in the example above?
Correct me if I am wrong but I think this is what you are trying to do:
var Dog = {
insert: function(props) {
console.log(props);
}
}
var insertArbitraryDocument = (function(collectionType, props) {
window[collectionType].insert(props)
}).bind(this);
insertArbitraryDocument('Dog', {name: 'skippy'}); //=> {name: 'skippy'}
In this snippet you are accessing the window object and getting the property of whatever name you are passing in (must be exactly the same as the collection). Then you can call your usual function calls.
I don't think there is a meteor built-in way of doing this, but it's pretty easy to just create a directory of collections manually:
JS in common to client and server:
var collections = {};
function myColl(name) {
var coll = new Meteor.Collection(name);
collections[name] = coll;
return coll;
}
// and now just use myColl instead of new Meteor.Collection
Dog = myColl('dog');
And then, to do what you want to do:
collections[i].insert(data);
Here's a complete working example:
Posts = new Mongo.Collection('posts');
Comments = new Mongo.Collection('comments');
var capitalize = function(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
};
var nameToCollection = function(name) {
// pluralize and capitalize name, then find it on the global object
// 'post' -> global['Posts'] (server)
// 'post' -> window['Posts'] (client)
var root = Meteor.isClient ? window : global;
return root[capitalize(name) + 's'];
};
var insertSomething = function(name, data) {
var collection = nameToCollection(name);
collection.insert(data);
}
Meteor.startup(function() {
// ensure all old documents are removed
Posts.remove({});
Comments.remove({});
// insert some new documents
insertSomething('post', {message: 'this a post'});
insertSomething('comment', {message: 'this a comment'});
// check that it worked
console.log(Posts.findOne());
console.log(Comments.findOne());
});
Note this is nearly identical to this question but I simplified the answer for more generic use.

Getting a username from ID without autopublish

I just got done with the rough draft of my app, and thought it was time to remove autopublish and insecure mode. I started transfering all the stray update and insert methods I had been calling on the client to methods. But now I'm having trouble returning a username from an ID.
My function before: (that worked, until I removed autopublish)
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var challenger = Meteor.users.findOne(post.challenger);
return challenger.username;
}
return false;
}
Now what I'm trying:
Template.lobby.helpers({
challenger: function() {
var postId = Session.get('activePost');
var post = Posts.findOne(postId);
if (post.challenger !== null) {
var userId = post.challenger;
Meteor.call('getUsername', userId, function (err, result) {
if (err) {
console.log(err);
}
return result;
});
}
return false;
},
Using:
Meteor.methods({
getUsername: function(userId) {
var user = Meteor.users.findOne({_id: userId});
var username = user.username;
return username;
},
...
})
I have tried blocking the code, returning values only once they're defined, and console.logging in the call-callback (which returned the correct username to console, but the view remained unchanged)
Hoping someone can find the obvious mistake I'm making, because I've tried for 3 hours now and I can't figure out why the value would be returned in console but not returned to the template.
Helpers need to run synchronously and should not have any side effects. Instead of calling a method to retrieve the user, you should ensure the user(s) you need for that route/template are published. For example your router could wait on subscriptions for both the active post and the post's challenger. Once the client has the necessary documents, you can revert to your original code.

Method call that fetches data. Can it be made reactive?

I want to get data from a number of queries on the same collection, and unfortunately this is not yet supported on meteor. That's why I tried to do something like this:
Common
Dep = new Deps.Dependency;
Server
Meteor.methods({
fetch: function(){
var results = Data.find(dataQuery).fetch();
var otherResults = Data.find(queryThatCannotBeCombinedWithPrevious).fetch();
return results.concat(otherResults);
},
save: function(data){
Data.insert(data);
Dep.changed();
}
update: function(data){
Data.update({_id: data._id}, data);
Dep.changed();
}
});
Client
Session.setDefault('combinedData', []);
Template.demo.data = function(){
Dep.depend();
Meteor.call('fetch',function(error, data){
Session.set('combinedData', data);
});
return Session.get('combinedData');
};
This doesn't work though, propably because the Dep variable on the client is different from the Dep on the server. Is there a way to make the method call reactive when the contents of the Data collection change?
Notes
I am currently using Meteor 0.8.1.1, which doesn't allow subscriptions that return multiple cursors of the same collection yet.
This requires a small hack and you're close. First, you need a client–only dependence, the server just passes a data returned from the method and doesn't share variables (also there's nothing on the server that requires deps). Second, you only want to fetch the actual variable once, otherwise you'll end up with an infinite loop.
Example implementation:
var value = null;
var valueInitialized = false;
var valueDep = new Deps.Dependency();
Template.demo.data = function() {
valueDep.depend();
if(!valueInitialized) {
valueInitialized = true;
Meteor.call('fetchData', function(err, result) {
value = result;
valueDep.changed();
});
}
return value;
};

Resources