Meteor Mongo findOne returns undefined in method - mongodb

This method is called by a helper attached to a post. For some reason, even though the user is definitely in the collection, I get TypeError: Cannot read property 'profile' of undefined from the method when it gets called. What's the deal?
userImage: function(user) {
var userObject = Meteor.users.findOne({ "username": user }, { profile: { image: 1 } });
return userObject.profile.image;
}
Peripheral question, can I just call a method in a helper like this and have it return right through to the helper in the template?
userImage: function() {
var user = this.username;
Meteor.call('userImage', user, function(error,id) {
if (error) {
return console.log(error.reason);
}
});
}

I think you mean:
Meteor.users.findOne({username: user}, {fields: {'profile.image': 1}});
You should probably add a guard after that like:
if(userObject && userObject.profile)
return userObject.profile.image;
See this question for how to call a method from your helper.

Related

Get data from subscribe in Ionic

I'm having difficulty getting data with subscribe in the constructor of an Ionic page, basically I need to do the subscribe to get a list and show to the user, but I get undefinied
In my constructor, I do this:
this.getUser(this.auth.currentUser().uid);
console.log(this.user);
My getUser():
getUser(uid) {
const self = this;
this.auth.getUserData(uid).subscribe(function(doc) {
if (doc.exists) {
self.user = doc.data();
} else {
console.log("No such document!");
}
});
};
But, when i call other function with button, i get the data:
userf(){
console.log(this.user);
}
Obs: I use Firestore
The reason it gives you undefined is because your method “getUser” is async and when you call console.log the user value is not yet obtained.
So you should access user value inside your getUser method after it is received.
Now also you are trying to pass “this” into the getUser method with const. start using fat arrow functions which do not create their own scope (this):
getUser(uid) {
this.auth.getUserData(uid).subscribe((doc) => {
if (doc.exists) {
this.user = doc.data();
} else {
console.log("No such document!");
}
});
};

Save records into the same collection in Mongo DB using Meteor js

Being new to Meteor JS, I'm confused on how to update a record. I have 2 templates AddSchoolLayout and Schoolcontactlayout, AddSchoollayout creates the record in Mongo db, now, for the same school I want to add its address still on the same DB NewSchoolDB but as I tried this I keep getting the error below about wrong ID. What wrong am I to right?
Note that my language might not correlate with Mongo's; I'm still fresh, coming from the SQL background.
This is the method.js where the record is been saved.
//methods.js
if (Meteor.isServer) {
Meteor.methods({
SchoolRegister: function (phone, schoolemail) {
if (!Meteor.userId()) {
throw new Meteor.error('Not authorized');
return false;
}else{
NewSchoolDB.insert({
authorId: Meteor.userId(),
phone: phone,
schoolemail
});
}
}
});
}
This is the event for saving a new school
//add school
Template.AddSchoolLayout.events({
'submit .addnewschool': function (event, template) {
event.preventDefault();
var newschoolname = trimInput(event.target.newschoolname.value);
if (isNotEmpty(newschoolname)) {
Meteor.call('SchoolRegister', newschoolname,
function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert("School successfully created", "success", "growl-top-right");
FlowRouter.redirect('/schoolcontact');
}
});
}
return false;
}
});
This is where I want to update the school address
//school contact
Template.SchoolContactLayout.events({
'submit .contactschool': function (event) {
event.preventDefault();
var phone = trimInput(event.target.phone.value);
if (isNotEmpty(phone)) {
Meteor.call('SchoolRegister', phone, function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert('School address updated successfully', 'success', 'growl-top-right');
FlowRouter.redirect('/logo-upload');
}
});
}
return false;
}
});
Error logged on the console
I20170524-17:44:14.051(1)? at packages/ddp-server/livedata_server.js:559:43
I20170524-17:51:54.678(1)? Exception from sub NewSchoolDB id onFTu2j3xRmbqC5WF TypeError: this.userId is not a function
I20170524-17:51:54.710(1)? at [object Object]._handler (lib/pulbish/published.js:3:13)
I20170524-17:51:54.712(1)? at maybeAuditArgumentChecks (packages/ddp-server/livedata_server.js:1737:12)
I20170524-17:51:54.713(1)? at [object Object]._.extend._runHandler (packages/ddp-server/livedata_server.js:1035:17)
I20170524-17:51:54.714(1)? at [object Object]._.extend._startSubscription (packages/ddp-server/livedata_server.js:853:9)
I20170524-17:51:54.715(1)? at [object Object]._.extend.protocol_handlers.sub (packages/ddp-server/livedata_server.js:625:12)
I20170524-17:51:54.719(1)? at packages/ddp-server/livedata_server.js:559:43
Your SchoolRegister method accepts 2 arguments: phone and schoolmail. When you create the school you call the methods with one argument called newschoolname. So something is wrong here with your naming convention, but it shouldn't really matter regarding your question.
With MongoDB, you use insert to add a new record to your collection. If you need to update it, use update. So one way to solve your problem is to:
In AddSchoolLayout, call your method to insert the document the first time. NewSchoolDB.insert(...) will return the ID of the created record. Keep that ID and pass it to your next page, for exemple in the URL.
In your next page, SchoolContactLayout, you need to call a new method which is going to update your school, using the ID returned by the previous method. This new method will look something like this:
SchoolUpdate: function (schoolId, phone) {
if (!Meteor.userId()) {
throw new Meteor.error('Not authorized');
return false;
}else{
NewSchoolDB.update(schoolId, { $set: { phone } });
}
}
The first argument of the update MongoDB function is the ID of the record you want to update. The second arguments are the modifiers you want to use to update your record. Here is the full list of modifier you can use: update modifiers
EDIT: how to pass ID from one layout to another:
I didn't use FlowRouter for a while and I can't test it right now so you may have to do some correction, but here is how I would do it to give you an idea:
First you need to define your route SchoolContactLayout with something like this:
FlowRouter.route('/schoolcontact/:schoolId', {
name: 'schoolContact',
});
This adds a schoolId parameter to the route.
In your SchoolRegister method, get the return ID and return it:
var id = NewSchoolDB.insert({
authorId: Meteor.userId(),
schooleName
});
return { id }
Edit your redirection FlowRouter.redirect('/schoolcontact'); with FlowRouter.go('/schoolcontact/' + response.id);
You can then edit your contactSchool event with something like this:
Template.SchoolContactLayout.events({
'submit .contactschool': function (event) {
event.preventDefault();
var schoolId = FlowRouter.getParam('schoolId');
var phone = trimInput(event.target.phone.value);
if (isNotEmpty(phone)) {
Meteor.call('SchoolUpdate', schoolId ,phone, function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
}else{
Bert.alert('School address updated successfully', 'success',
'growl-top-right');
FlowRouter.redirect('/logo-upload');
}
});
}
return false;
}
});
Notice the var schoolId = FlowRouter.getParam('schoolId'); to get the ID from URL parameter so I can use it in the update method.

Meteor - How can I find/get an object in a MongoDB collection and push it into another collection with a method?

I have a server side method like:
Meteor.methods({
'pushInfo': function(){
if (this.userId) {
userManagement.update({
'_id': this.userId
}, {
$push: {
'activeInfos': ["The Info/Object I want to push from another collection"]
}
}
);
}
}
});
This method should push an object into the field 'activeInfos' inside the collection 'userManagement'.
I have a click. event which triggers the method like:
Template.available.events({
"click. push": function(e) {
e.preventDefault();
Meteor.call('pushInfo');
}
});
Now, I have another collection called 'Infos' from where I want to push the single objects/ID´s into the field 'activeInfos' via the method.
The method works like expected when I manually fill it with an ID from the 'Infos'-collection. It pushes this ID into 'activeInfos' and the user can now access this objectID from 'Infos'.
However, it should automatically find the right ID from 'Infos' and push it into 'activeInfos', when the method is triggered.
Is there any way to do that?
Got it! However, thanks for your effort! I don´t know why, but I just had to assign this.InfoId to a var and put InfoId into the Meteor.call within the event handler. Than I was able to pass this var into the function within the server side method and grab it for the $push.
Template.available.events({
"click .push": function(e) {
e.preventDefault();
var InfoId = this.InfoId;
Meteor.call('pushInfo', InfoId);
}, });
and
Meteor.methods({
'pushInfo': function(InfoId) {
if (this.userId) {
userManagement.update({
'_id': this.userId
}, {
$push: {
'activeInfos': infoId
}
}
);
}
}
});
If your available template is showing a list of Infos then you can get the _id of the Infos object in your event handler and pass it to the method:
Template.available.events({
"click. push"(e) {
e.preventDefault();
Meteor.call('pushInfo',this.InfoId);
}
});
Meteor.methods({
'pushInfo'(infoId)=>{
const info = Infos.findOne(infoId)
if (this.userId && info) {
userManagement.update(this.userId, { $push: { activeInfos: info }});
}
}
});

sails.js the return object from service is undefined when using a find query

I created a service called AppService.
Its function getUserPostionOptions is supposed to return an object:
getUserPostionOptions: function (user) {
// PositionOptions.findOne({id:'53f218deed17760200778cfe'}).exec(function (err, positionOptions) {
var positionDirectionsOptions = [1,2,3];
var positionLengthsOptions = [4,5,6];
var object = {
directions:positionDirectionsOptions,
lengths:positionLengthsOptions
};
return object;
// });
}
This works, in my controller positionOptions gets populated correctly:
var positionOptions = AppService.getUserPostionOptions(user);
However, when I uncomment the find query the item is found but the object returns undefined.
Thank in advance for your help
SailsJs ORM (and almost NodeJs database querying methods) uses non-blocking mechanism via callback function. So you have to change your code into:
getUserPostionOptions: function (user, callback) {
PositionOptions.findOne({id:'53f218deed17760200778cfe'}).exec(function (err, positionOptions) {
var positionDirectionsOptions = [1,2,3];
var positionLengthsOptions = [4,5,6];
var object = {
directions:positionDirectionsOptions,
lengths:positionLengthsOptions
};
callback(null, object); // null indicates that your method has no error
});
}
Then just use it:
AppService.getUserPostionOptions(user, function(err, options) {
if (!err) {
sails.log.info("Here is your received data:");
sails.log.info(options);
}
});

Call controller on afterCreate

I have the following code for my Sessions model:
module.exports = {
attributes: {
},
afterCreate: function(value,next) {
next();
}
};
And the following Sessions Controller:
module.exports = {
saveSession: function(res,req) {
console.log('in save');
}
};
I want to save a value to a user's session afterCreate
How can I call the saveSession function from my model? I tried Sessions.saveSession() but it doesn't work.
I don't think you need a session model and it's not a good idea to call a controller method directly.
I'd recommend just set req.session when you're trying to save the session and it'll be auto-saved when you respond from that controller action.
afterCreate will never have access to req unless you pass it down which I wouldn't recommend.
The pattern is something like:
{
// …
login: function (req,res) {
User.findOne({
username: req.param('username'),
password: req.param('password')
}).exec(function (err, user) {
if (err) return res.serverError(err);
if (!user) return res.view('/login');
req.session.user = user.toJSON();
return res.redirect('/dashboard');
});
}
// ...
I think that you want to save a value to a cookie or create another database record am i correct?
If so, you dont need to call a controller action from the model (not recommended), you just need to create a new record or save the value to the cookie, here are some alternatives that i see possible in your scenario.
creating another record:
// on models/YourModel
module.exports = {
attributes: {
},
afterCreate: function(newlyInsertedRecord,next) {
ModelOrResource.create({
param1: newlyInsertedRecord.attributeYouWant,
param2: value2
// and so on
}).exec(function(err, recordCreated){
if(err) return next(err);
// do somethign with recordCreated if you need to
// ...
next();
})
}
};
Saving a value to a cookie:
module.exports = {
attributes: {
},
afterCreate: function(newlyInsertedRecord, next) {
// do some other stuff not related to calling a controller action ;)
next();
}
};
This code was retrived from snippets from my own projects, so it should work on sails 0.9.x
Hope it helps!