Firebase AngularFire using $priority and the $save overwrites the object - angularjs

Based on the AngularFire documentation I'm trying to set $priority on an object, then use $save() to update the data on Firebase.
The result I get instead is the object getting overwritten as empty (it's entry in Firebase).
Here is my code
var ref = new Firebase(firebaseListPath);
var myList = $firebase(ref).$asArray();
myList.$add({
created: Firebase.ServerValue.TIMESTAMP,
user: userId
}).then(function(newItemRef){
var newItemObj = $firebase(newItemRef).$asObject();
newItemObj.$priority = userId;
newItemObj .$save();
});

Try passing the priority directly into $add:
myList.$add({
created: Firebase.ServerValue.TIMESTAMP,
user: userId,
$priority: userId
});
There is also no reason to call $asArray and $asObject on the same synchronized data (it's already synchronized). This would work in your current model, but be unnecessary:
myList.$add({
created: Firebase.ServerValue.TIMESTAMP,
user: userId
}).then(function(newItemRef){
var item = myList.$getRecord(newItemRef.name());
item.$priority = userId;
myList.$save(item);
});
However, there is really no reason to be using AngularFire here. If you aren't binding anything to the view, then you can simply make the call directly to the ref:
var ref = new Firebase(firebaseListPath);
ref.push().setWithPriority({ ... }, userId);

Related

Update boolean with Mongoose

I have created an app where i can create a to do list. And i have a status that is false when created. The status i supposed to represent if the object done or not.
My mongoose schema look like this in server.js:
// Create mongoose schema
var issueSchema = mongoose.Schema ({
issue: String,
date: String,
status: Boolean,
});
// Create mongoose model
Issue = mongoose.model('Issue', issueSchema);
When i press my button in on my index.html im using angular to send the id trough to the server.js file.
// API PUT ========================
app.put('/issueList/:id', function(req, res){
var id = req.params.id;
Issue.findById(id, function(err, Issue) {
console.log("Object with ID: " + id); // Correct ID
// I need code here
});
});
I need help updating the boolean value to true if false or false if true. Or should i skip the boolean value and use something else?
You can find the issue by id and then save it back to MongoDB after making the changes in success callback.
Issue.findById(id, function(err, issue) {
issue.status = !issue.status;
issue.save(function (err) {
if(err) {
console.error('ERROR!');
}
});
});
I am not sure about the possibility of toggling boolean field atomically as of now in MongoDB.
First, i dont think you should use same variable name outside and inside the function. In this case Issue is same, change it to issue.
And you can try this to update.
Issue.findById(id, function(err, issue) {
console.log("Object with ID: " + id); // Correct ID
issue.status = !issue.status;
issue.save(function(err,result){...});
});
});

AngularFire: Getting the ID of Users Data from email in SimpleLogin

I'm trying to implement some simple using registration using Firebase through AngularFire and Angular.js. I'm using the SimpleLogin tool to manage the users. I can create users just fine.
var firebaseRef = new Firebase(FIREBASE_URL);
var simpleLogin = $firebaseSimpleLogin(firebaseRef);
var firebaseUsersRef = new Firebase(FIREBASE_URL + 'users');
var firebaseUsers = $firebase(firebaseUsersRef);
var myObject = {
register: function(user) {
var myDate = new Date().getTime();
return simpleLogin.$createUser(
user.email, user.password)
.then(function(regUser) {
var userInfo = {
date: myDate,
md5: regUser.md5_hash,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$push(userInfo).then(function(ref) {
userInfo.uid = ref.name();
$rootScope.currentUser = userInfo;
});
}); //push user
}, //register
Works like a charm. In order to get at this information when the user logs in, I've tried implementing an event handler on the $rootscope. I would like it to search through the uid that I stored and then get me record with the right user information.
$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var query = $firebase(firebaseRef.startAt(authUser.uid).endAt(authUser.uid));
console.log(query);
$location.path('/meetings');
});
In order to use startAt and endAt, do I have to establish $priority. When I try, I get an error stating that I can't have any special characters. So that never works. I don't really care about how this data stored, I just want to get the index of the data so that I can retrieve the right user.
By using $push you tell Firebase to generate a key for you.
This is great for collections where you normally access all children at the same time. But that is not the case for your user info: you want to access the info for the current user.
So instead of using $push to add your user's info, I would use the uid of the user.
In the regular Firebase JavaScript API this can be accomplish with:
firebaseUsersRef.child(reguser.uid).set(userInfo);
The equivalent in AngularFire probably uses $set, but I don't think you have any need for that in your $createUser callback.
Update
It looks like you're trying to add your info to the existing user node that Firebase creates for you. This is the example from that from the Firebase documentation on storing user data:
myRef.child('users').child(user.uid).set({
displayName: user.displayName,
provider: user.provider,
provider_id: user.id
});
You can see that they do access the user's node using child(user.uid) similar to what I proposed.
Lessons
Two relatively small mistakes here as far as I can see:
when you use push/$push, you let Firebase generate the node name for you. In cases where there already is a globally unique ID (such as the uid of a user), you're often better off using that as the node name.
If you know the name of the node you want to retrieve, you don't need a query. You can simply access the node as ref.child(user.uid).
Thanks to Frank, I was able to figure out the right way to do this. In order to make my own users object searchable, I can use the uid from the simpleLogin object. So my register function works like this:
var firebaseRef = new Firebase(FIREBASE_URL);
var simpleLogin = $firebaseSimpleLogin(firebaseRef);
var myObject = {
register: function(user) {
var myDate = new Date().getTime();
return simpleLogin.$createUser(user.email, user.password)
.then(function(regUser) {
var userInfo = {
date: myDate,
md5: regUser.md5_hash,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$set(regUser.uid, userInfo);
}); //add user
}, //register
} //my Object
Using set instead of push, I can store the uid from the registered user into the object and then pass along what I want to add as the second parameter. My database will now have the users organized by uid, which can be accessed via a url.
Then, when users log in, Firebase will throw up a login event along with the authenticated user, which I can catch and use to add the current user to the $rootScope that's accessible throughout my application.
$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var ref = new Firebase(FIREBASE_URL + '/users/' + authUser.uid);
var user = $firebase(ref).$asObject();
user.$loaded().then(function() {
$rootScope.currentUser = user;
});
$location.path('/meetings');
});
Thanks for pointing me in the right direction Frank.

How to do a query using dot( . ) through Mongoose in Node.js and How to add an empty array

I have the following schema:
var userSchema = new Schema({
userID: Number,
userName: String,
userEmail: String,
teams:Array,
socialMedias:
{
fbUID: String,
googleUID: String,
twitter: String }
});
First, How can I add an empty array? Is it right the way I am doing in the following?
teams:{},
Second, I am trying to do a query using Mongoose in my Node.js but I am getting an error in the dot ('.'):
This is my document I am saving:
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail',
teams:{},
socialMedias: [{socialMediaType: socialMediaID}]
});
where userName, socialMediaType and socialMediaID are parameters of a function.
So, after I add this doc, I am trying to do the following query:
function searchUser(socialMediaID, socialMediaType){
var user
users.findOne({socialMedias.socialMediaType: socialMediaID}, function(err, userFound){
if(err) return handleError(err);
user = userFound;
});
//what does MongoDb return if it does not find the document?
return user;
}
but I am getting an error in this :
socialMedias.socialMediaType
So, how can I do this query?
I tried to find in Mongoose Documentation but I did not find.
Thank you for your understanding.
There's a number of issues here that you are likely running into.
First, teams is an array property, but you're assigning an object to it. You need to do something like this:
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail',
teams:[],
socialMedias: [{socialMediaType: socialMediaID}]
});
Second, if socialMediaType is passed in as a function param, you can't use it like you're doing. You need to do something like this:
var socialMedias = {};
socialMedias[socialMediaType] = socialMediaID;
var user = new users({
userID: id, //give the id of the next user in Dbase
userName: userName,
userEmail: 'userEmail',
teams:[],
socialMedias: [socialMedias]
});
Third your findOne is not going to work as is. From what I can gather of your intention here, you need something like this:
function searchUser(socialMediaID, socialMediaType){
var user
var query = {};
query["socialMedias."+socialMediaType] = socialMediaID;
users.findOne(query, function(err, userFound){
if(err) return handleError(err);
user = userFound;
});
//what does MongoDb return if it does not find the document?
return user;
}
But fourth, even that won't work because you are synchronously returning user from a method that performs and asynchronous operation. There are various ways to solve that, but you can start by reading up about promises, or passing a callback function into searchUser.

firebase/angularFire querying with startAt/endAt doesn't work

I have an app where I use FirebaseSimpleLogin, but since I have additional user data, I store it under [my-firebase].firebaseio.com/users/[username]. The snippet below shows how it's done
var User = {
create: function (authUser, username) {
users[username] = {
md5_hash: authUser.md5_hash,
username: username,
email: authUser.email,
$priority: authUser.uid
};
users.$save(username).then(function () {
setCurrentUser(username);
});
},
...
Since data for each individual user, are keyed based on username I prioritize by uid, so I can later fetch additional user data by uid.
When the firebase login event fires, I have the following handler, that is responsible for querying firebase to get the additionala user data, and store it on $rootScope.currentUser via a method setCurrentUser(username)
Here is my login event handler:
var ref = new Firebase(FIREBASE_URL + '/users');
var users = $firebase(ref);
$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var query = $firebase(ref.startAt(authUser.uid).endAt(authUser.uid));
query.$on('loaded', function () {
//PROBLEM: console.log(query.$getIndex()) logs an empty array
setCurrentUser(query.$getIndex()[0]);
});
});
As soon as the login event fires, I get access to the authUser, which contains the uid of the logged in user. Then I query firebase /users by uid, using startAt/endAt to limit my results so that I'm left only with the currently logged in user.
Then, when the query data is loaded from firebase, I invoke the setCurrentUser method which stores the username of the currentUser on $rootScope.
The Problem
The query filtering using startAt/endAt does not work, I'm getting back an empty array when I console.log query.$getIndex() when I should be getting an array with the username of the currently logged-in user.
I'm using firebase 1.0.15, angularFire 0.7.1 and firebase-simple-login 1.4.1 and following this tutorial from Thinkster.io
In the end somewhere in my code I had a $save() on my user binding, to save the id of the last project they've been working on, and this was causing the $priority issue. I used $update instead, and now everything works like a charm!
Still I don't know if this is intended behavior of $save()
To clarify and provide more context, I wasn't passing any keys to the $save() method, I simply added a property on my local user reference, and saved it
$rootScope.currentUser.lastWorkingProject = projectId;
$rootScope.currentUser.$save();

why does backbone think I'm treating an object like a function?

Adding Backbone to a Rails app, I created a post model inside an app namespace like this
var app = {
this.models.post = new app.Models.Post();
In the router, I created the following route
"posts/:id": "postDetails"
When I navigate to /posts/4, I'm getting an Uncaught TypeError: object is not a function error when I try to call fetch on the model like this
postDetails: function (id) {
console.log(id);
var post = new app.models.post({id: id});
this.post.fetch({
success: function (data) {
$('#content').html(new PostView({model: data}).render().el);
}
});
}
According to the Backbone docs http://backbonejs.org/#Model-fetch, I should be able to call fetch on a model to retrieve the data from the server. Why does Backbone think I'm treating an object like a function?
You're doing this:
this.models.post = new app.Models.Post();
to, presumably, set app.models.post to an instance of the app.Models.Post model. Then you try to do this:
var post = new app.models.post({id: id});
But you can only use the new operator on a function:
new constructor[([arguments])]
Parameters
constructor
A function that specifies the type of the object instance.
You probably want to say:
var post = new app.Models.Post({ id: id });
or something similar.
The problem is you've declared post as a local variable var post, but then tried to access it as a member this.post. You need either this:
this.post = new app.models.post({id: id});
this.post.fetch({ ...
Or this:
var post = new app.models.post({id: id});
post.fetch({ ...
(The difference being that a local variable var post is declared in transient scope and thrown away after postDetails completes; while instance variable this.post gets added to the Router object and will typically live for the whole lifetime of the application.)

Resources