I have 2 collection tables that only share emails as the unique ids of these 2 tables. The first one is Meteor.users() and SchoolStudents. I want to update the SchoolStudents collection based on the user's email. Though I have successfully updated using _id but the update isn't working using email as the Id. What's the better approach?
In this, it returned a success feedback but no update is made to the record. Bert.alert('Record updated successfully', 'success', 'growl-top-right');
Client code:
let user = Meteor.user();
let studentemail = user && user.emails && user.emails[0].address;
if (studentemail) {
console.log(studentemail);
Meteor.call('UpdateUser', studentemail, function (error, response) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
return false;
} else {
Bert.alert('Record updated successfully', 'success', 'growl-top-right');
}
})
}
Server method
SchoolStudents.update({useremail: studentemail}, {$set: {'status.active': true, 'status.activedate': new Date()}});
This is a sample document from the SchoolStudents collection:
{
"_id" : "xgxZJFRkXGhHmHupY",
"firstname" : "Kehinde",
"lastname" : "Adeoya",
"middlename" : "Adekusibe",
"username" : "ken10ward",
"password" : "PvyLwY9d",
"useremail" : "kadeoya#appzonegroup.com",
"studentclass" : "ss8",
"dateofbirth" : "9-Mar-00",
"gender" : "f",
"ethinicity" : "black",
"mobile" : "8023472442",
"address" : "7 Abrahamoivc",
"city" : "bolson",
"lg" : "loveland",
"state" : "ekiti",
"country" : "Ukraine",
"registra" : "kadeoya",
"status" : {
"active" : false,
"activedate" : null
},
"userId" : "n5rqFSHbhm7zqADyB",
"createdAt" : ISODate("2017-09-05T18:45:14.877Z"),
"friendlySlugs" : {
"slug" : {
"base" : "kehinde-adeoya",
"index" : 5
}
},
"slug" : "kehinde-adeoya-5"
}
This is the server update code:
UpdateUser: function (studentemail) {
check(studentemail, String);
if (!Meteor.userId()) {
Meteor.Error('Not authorized');
return false;
} else {
SchoolStudents.update({useremail: studentemail}, {status: {active: true, activedate: new Date()}}, { upsert: true });
}
}
As it has been pointed to you, you're using user && user.emails && user.emails[0].address construct wrong way.
I suggest you to use this template to do things like that:
let studentemail;
try {
studentemail = user.emails[0].address.valueOf();
} catch (e) {
studentemail = null;
}
if (studentemail != null) {
...
}
This way you can omit numerous checks, like user != null and user.emails != null and user.emails.length > 0 etc and it will be guaranteed that in your studentemail variable you will get either null or user email address.
Added: User email address could be undefined, that's why you need != null check (non-strict). It will be false if variable is undefined or null.
Related
I am attempting to output a set of a data from a real-time database into html elements, I have no issues in taking the data from the server and using setState to save the data. I have a custom HTML object from a functional Component that will output props, but I am unable to map the object and the inner objects.
Here is the code responsible for pulling the data from the database:
componentDidMount() {
axios.get('./tasks.json')
.then(response => {
const fetchedTasks = [];
for (let key in response.data) {
fetchedTasks.push({
...response.data[key],
key: key
});
}
this.setState((prevState, props) => {
return {
taskList: fetchedTasks
}
} )
})
.catch(error => console.log(error));
}
And this is the data I am pulling from the database. I want to be able to display each item per it's name, id etc.
This is an export of the JSON data from the server, this is the copied into the state of my class component via the axios.get call 'Past.js'
{
"tasks" : {
"09182018" : {
"-LMgzJGM78f0BHbPf8cc" : {
"hours" : 0,
"id" : "2018-09-18T14:02:25.022Z",
"minutes" : 0,
"name" : "sadflkjdsalkf",
"seconds" : 2,
"start" : "2018-09-18T14:02:22.508Z"
},
"-LMgzaEYe0tcCjpxOuPU" : {
"hours" : 0,
"id" : "2018-09-18T14:03:38.635Z",
"minutes" : 0,
"name" : "safd",
"seconds" : 2,
"start" : "2018-09-18T14:03:36.353Z"
}
},
"09192018" : {
"-LMm7EoPnNdQLrZ5Rg62" : {
"hours" : 0,
"id" : "2018-09-19T13:59:31.361Z",
"minutes" : 0,
"name" : "sadf",
"seconds" : 2,
"start" : "2018-09-19T13:59:29.281Z",
"user" : "placeholder"
}
},
"09212018" : {
"-LMve6ihcRX_uZfvBcaC" : {
"hours" : 0,
"id" : "2018-09-21T10:24:06.504Z",
"minutes" : 0,
"name" : "sadfsd",
"seconds" : 2,
"start" : "2018-09-21T10:24:03.841Z",
"user" : "placeholder"
},
"-LMvnBBAWaHaBiGW5VMK" : {
"hours" : 0,
"id" : "2018-09-21T11:03:44.420Z",
"minutes" : 0,
"name" : "hello",
"seconds" : 14,
"start" : "2018-09-21T11:03:29.802Z",
"user" : "placeholder"
}
}
}
}
I have attempted to run .map() calls on the state with no luck, mapping the nested item throws 'array.map is not a function'. This is the code I have so far:
render() {
let outPutItems = [];
if (this.state.loading === false) {
outPutItems = this.state.taskList.map(array => array.map(item => {
<CompleteTask
id={item.id}
taskName={item.name}/>
})
)}
return (
<div className="Past">
<h1>Past Tasks</h1>
{outPutItems}
<button onClick={this.collectTasks}>Log the TaskList!</button>
</div>
);
}
-UPDATE
The top three are what I am able to use in react and the bottom is using dummy data and is my desired output from the JSON data above which has been applied to the state from the firebase server.
top output with map method, bottom using placeholder data from state
I am able to output the top three shown with this code, all other code above is the same:
{this.state.taskList.map((outer, index) => (
<CompleteTask
taskName={outer.key}
/>
) )
}
This should work for you. Taken from here. In addition, theres no need to check if loading == false before rendering a list. If there is nothing in the list to be rendered, nothing will render. Also, as soon as the list is populated it will reflect in the view.
return (
<div className="Past">
<h1>Past Tasks</h1>
{this.state.taskList.map((item, index) => (
<CompleteTask id={item.id} taskName={item.name}/>
)}
<button onClick={this.collectTasks}>Log the TaskList!</button>
</div>
);
This is currently how my firebase database looks.
I am trying to perform an update where when I click the like button, the user will appear in liked attribute (the second one above). currently it is just hardcoded but the code is not doing quite what i want it to do.
function liked(name, useruid, user_liked){
var postData = {
name: name,
useruid: useruid,
user_liked: user_liked
};
var newPostKey = firebase.database().ref().child('users').push().key;
var updates = {};
updates['/users/' + name + '/' + '/liked/' + user_liked] = postData;
return firebase.database().ref().update(updates);
}
I call this function with liked(current_user_name, user_array[i].useruid, 'Hannah')
I would like then the liked: "liked attribute to read liked: "liked", "Hannah"
However instead it does the following below:
It has added in information I do not want and instead of adding to the array it has transformed it. it must be a tiny change but i cant quite see it
exported json before update:
{
"users" : {
"rich" : {
"gender" : "male",
"liked" : "liked",
"name" : "rich",
"not_liked" : "liked",
"username" : "rich#rich.com",
"useruid" : "5xO85K2EBOS6Itj7lKoGafm19i02"
}
}
}
exported json after update:
{
"users" : {
"rich" : {
"gender" : "male",
"liked" : {
"Hannah" : {
"name" : "rich",
"user_liked" : "Hannah",
"useruid" : "5xO85K2EBOS6Itj7lKoGafm19i02"
}
},
"name" : "rich",
"not_liked" : "liked",
"username" : "rich#rich.com",
"useruid" : "5xO85K2EBOS6Itj7lKoGafm19i02"
}
}
}
. Sample of collection Flights :
{
"Orig" : "AGP",
"Dest" : "CMN",
"Description_Flight" : "One-Stop-Narrow Type",
"Description_Flight_2" : "WESTERN EUROPE/WESTERN EUROPE",
"Mkt_Al" : "0B"
}
. Sample of collection Coeff :
{
"Regions" : "WESTERN EUROPE/WESTERN EUROPE",
"Non-Stop-Narrow Type" : 2.4109,
"Non-Stop-Supersonic" : 2.71828,
"One-Stop-Narrow Type" : 2.22554,
"One-Stop-Turbo" : 0.92312,
"One-Stop-Wide Type" : 11.24586,
"One-Stop Online-Turbo" : 0.07577
}
What I want ?
I Have my starting collection, Flights and for each document I want to put a score, a score which based on the Description_Flight_2 and Description_Flight.
Example :
For example, in my sample I have :
"Description_Flight" : "One-Stop-Narrow Type",
"Description_Flight_2" : "WESTERN EUROPE/WESTERN EUROPE",
So, I should go to the Coeff collection, and find the region :
"WESTERN EUROPE/WESTERN EUROPE"
and then take the appropriate value, here I should take this value in this line :
"One-Stop-Narrow Type" : 2.22554,
I have tried this :
mongoose.connect('mongodb://localhost/mydb');
var cSchema = new Schema({},{ strict: false, collection: 'flights' }),
dflights = mongoose.model("flights", cSchema);
var rSchema = new Schema({},{ strict: false, collection: 'coeff' }),
coeff = mongoose.model("coeff", rSchema);
mongoose.set('debug', false);
mongoose.connection.on("open", function (err) {
if (err) throw err;
dflights.find({}).lean().exec(function (err, flights) {
if (err) throw err;
flights.forEach(function(flight) {
var Flight_Description = "", score =0 ;
coeff.findOne({Regions : flight.Description_Flight_2}).lean().exec(function (err, coef) {
And here the important lines :
Flight_Description = flight.Description_Flight;
score = (coef != null ) ? coef.Flight_Description : "Missed data";
Here the last lines
if ( score != 0)
dflights.collection.update({_id:flight._id}, { $set : { score :score } } );
});
});
});
});
Please how can I achieve the above ?
The correct code should be:
score = (coef != null ) ? coef[Flight_Description] : "Missed data";
How to check if current Meteor.user()._id exists in "favoritedBy" array?
If true, print "Your favorite", if false, print "Not your favorite".
Document in MongoDB:
{
"_id" : "W5WwAZatorDEb6DNP",
"createdBy" : "aTmb64zNGSyeDYFJZ",
"favoritedBy" : [
"X594baqWYZiJqA3Qg",
"fgk234m2dkD229d12"
]
}
Say that Meteor.user()._id returns X594baqWYZiJqA3Qg.
How can I do a true/false check on this?
I tried the following:
isFavorite: function() {
var user = Meteor.user()._id;
return Posts.find({favoritedBy: user});
}
In the template:
{{#if isFavorite}}
Your favorite
{{else}}
Not your favorite
{{/if}}
But it don't seem to work, as it always return as "Your favorite", even if current Meteor user id is not in the array.
Any ideas?
you can use
isFavorite: function() {
var user = Meteor.user()._id;
return Posts.find({favoritedBy: user}).count() > 0 ? true : false;
}
count() will returns the count of documents that would match a find() query then check if its > 0 , and by using ternary operator, if yes it will return true if not it will return false
I'm building a forum, and I'm in the step of views. I have this (simplified) code:
//Setting Views
//Adding Them..
$scope.views = $firebaseObject(refService.ref().child("Topics"))
refService.ref().child("Topics").once("value", function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key();
var childData = childSnapshot.val();
if(childData.DateCreated == $stateParams.DATE && childData.Email == $stateParams.EMAIL){
refService.ref().child("Topics").child(childData.pushKey).child("Views").child(currentAuth.uid).set({
Views : true
})
}
})
})
//Viewing them
$scope.viewableView = $firebaseObject(refService.ref().child("Topics"))
As you can see adding the views was pretty easy job. And I did it correctly. The problem is with displaying the number of views, and I have to do it using AngularFire's $firebaseObject, or $firebaseArray... Here is the structure in database:
{
"Topics" : {
"-KG9rDNLZksJDiLfAXwH" : {
"Avatar" : "http://cs624223.vk.me/v624223037/2b1bb/GRTKddkmXiw.jpg",
"DateCreated" : 1461544873669,
"Email" : "abogale2#gmail.com",
"Title" : "Check",
"UID" : "3caf2136-7a2d-4ae4-a4a9-119f2b08133c",
"Username" : "BruhBrhu",
"Value" : "Check",
"Views" : {
"3caf2136-7a2d-4ae4-a4a9-119f2b08133c" : {
"Views" : true
}
},
"pushKey" : "-KG9rDNLZksJDiLfAXwH"
}
},
"UserAuthInfo" : {
"3caf2136-7a2d-4ae4-a4a9-119f2b08133c" : {
"BronzeBadge" : 0,
"Description" : "Just a wierd 15 year old coder...",
"Email" : "abogale2#gmail.com",
"GoldBadge" : 0,
"Image" : "http://cs624223.vk.me/v624223037/2b1bb/GRTKddkmXiw.jpg",
"Moderator" : false,
"Password" : "KfUcQ1yedOi1gEnGP6i1KQ==",
"PlatinumBadge" : 0,
"SilverBadge" : 0,
"UID" : "3caf2136-7a2d-4ae4-a4a9-119f2b08133c",
"Username" : "BruhBrhu"
}
}
}
As you can see I used push(), to get the topic.. My Concern now is how to view the topics! Please Help! I can't think of a "algorithm" to do it!
Mind you, all of the topics have unique ID's. I have to get the specific ID The user is in.
This worked for me:
refService.ref().child("Topics").once("value", function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key();
var childData = childSnapshot.val();
if(childData.DateCreated == $stateParams.DATE && childData.Email == $stateParams.EMAIL){
refService.ref().child("Topics").child(childData.pushKey).child("Views").on("value", function(snapshot){
console.log(snapshot.numChildren())
$scope.countViews = snapshot.numChildren();
})
}
})
})
I dont know how but somehow $scope.countViews, became three way binded to my HTML, so it actually shows!
You're nesting keys inside an object, which the Firebase documentation explicitly recommends against.
But it can work once you realize that you can also add methods to the scope:
var app = angular.module('app', ['firebase']);
app.constant('FB_URL', 'https://yours.firebaseio.com/');
app.controller('MainCtrl', function(FB_URL, $scope, $firebaseArray, $firebaseObject) {
var ref = new Firebase(FB_URL);
$scope.topics = $firebaseArray(ref.child('Topics'));
$scope.getCount = function(obj) {
return Object.keys(obj).length;
};
});
And the view:
<body ng-controller='MainCtrl'>
<ol><li ng-repeat='topic in topics'>{{topic.Title}} - {{topic.Username}} - {{getCount(topic.Views)}}</li></ol>
</body>
Working jsbin: http://jsbin.com/dapoga/edit?html,js,output