Parse save() from the client gets changes done in beforeSave? - parse-platform

Using parse from an Ios/Android app, I create a new object of my class "Tomato" and call save() or saveInBackground(...).
In this class "Tomato" beforeSave hook, I initialise some fields with custom values.
My question is, are those values available in the client after the save is completed? Or do i need to fetch the object after save it?

You would need to fetch it again to get access to the values created in beforeSave (note that refresh is deprecated and Parse now wants you to use fetch):
https://parse.com/docs/ios/api/Classes/PFObject.html#//api/name/fetch:

You have the updated object in the save callback:
gameScore.save(null, {
success: function(object) {
// The object was saved successfully.
},
error: function(object, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
}
});
Android
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.saveInBackground();
After this code runs, you will probably be wondering if anything
really happened. To make sure the data was saved, you can look at the
Data Browser in your app on Parse. You should see something like this:
objectId: "xWMyZ4YEGZ", score: 1337, playerName: "Sean Plott", cheatMode: false,
createdAt:"2011-06-10T18:33:42Z", updatedAt:"2011-06-10T18:33:42Z"
Source: https://parse.com/docs/android/guide#objects-saving-objects

Related

unable to pull data from browser.storage.local.get

trying to implement options page for a firefox addon/extension version 64.0. I am using browser.storage.local.set to store data. but when I use browser.storage.local.get to pull the data, the result is <unavailable> on the console log.
the following is the function i run in my options.js file (i entered njnj on the form field gateway and hit the submit button)
function saveOptions(e) {
e.preventDefault();
console.log("you are here")
console.log(document.querySelector("#gateway").value)
browser.storage.local.set({
"gateway": document.querySelector("#gateway").value });
console.log(browser.storage.local.get("gateway"))
}
document.querySelector("form").addEventListener("submit", saveOptions);
my actual output in the console log is as follows :
you are here options.js:4:3
njnj options.js:5:3
<unavailable> options.js:8:3
ok so I did figure out partly why the above code is not working. the problem is that browser.storage.local.get() returns a 'promise' in javascript (I dont actually know what it means yet). So you have to have a code that will actually retrieve the answer/saved value from this 'promise'. I will give you an example on how to retrieve the value:
// first save a key value pair into storage
browser.storage.local.set({"key": 'value'})
// to retrieve this value, first declare a new variable
var savedvalue = "zero"
// retrieve the 'promise' of key value pair, then run the associated function to get
//the savedvalue and set it equal to previously declared variable.
browser.storage.local.get(['key'], function(result) {savedvalue = result.key});
// now, when you call savedvalue (even outside the function above), it will return 'value'
console.log(savedvalue)
output>> value
You could use async function and await, like this
async function saveOptions(e) {
e.preventDefault();
await browser.storage.local.set(
{ "gateway": document.querySelector("#gateway").value }
);
}
document.querySelector("form").addEventListener("submit", async saveOptions);
You don't need to pass the 'e' to the function, you're not doing anything with it.
You could also refactor it this way, if the mood took you
document.querySelector("form").addEventListener( "submit", async ()=> {
e.preventDefault();
await browser.storage.local.set(
{ "gateway": document.querySelector("#gateway").value }
);
});
The question is really about how to get/handle the value of a Promise in async Javascript (which the browser.storage.local.get() method is).
browser.storage.local.get('gateway').then(
function (result) {
// code goes here
console.log(result.gateway);
}).catch(function (error) {
// error code
});
see How can I access the value of a promise?

parse background job each() does not go through all records?

I wrote a cloud job to insert a lowercase version of a user's first name and last name in the user object so that I can perform a search from my client app.
When I did run this job on a dev parse app that had like 40 users it worked great.
When I did run this on my production app however it did not update all of my records. I have a few thousands users at the moment and I was expecting this cloud job to take care of all of them as explained here:
http://blog.parse.com/2013/05/13/launch-and-iterate-parse-data-migrations/
" The new each method on Parse.Query objects allows you to do just that. Even if you have tens of thousands of objects or more in a collection, it will return each one of them, giving you an opportunity to modify them as you see fit."
So then my question is why does this function leave behind over half of my database? It only worked on a bunch of users, maybe a few hundred.
How can I make this function affect my WHOLE DATASET in the User table?
Parse.Cloud.job("migration1", function(request, status) {
// Set up to modify user data
Parse.Cloud.useMasterKey();
// Query for all users
var query = new Parse.Query(Parse.User);
query.each(function(user) {
// Set and save the change
var firstname = user.get("firstname");
if(firstname) {
user.set("searchfirstname", firstname.toLowerCase());
} else {
user.set("searchfirstname", "");
}
var lastname = user.get("lastname");
if(lastname) {
user.set("searchlastname", lastname.toLowerCase());
} else {
user.set("searchlastname", "");
}
return user.save();
}).then(function() {
// Set the job's success status
status.success("search migration completed successfully.");
}, function(error) {
// Set the job's error status
status.error("Uh oh, something went wrong with search migration");
});
});
EDIT:
Ok so when I look at the error logs I see this:
E2014-10-18T15:48:49.984Z] v63: Ran job searchMigration with:
Input: {}
Failed with: TypeError: Cannot call method 'toLowerCase' of undefined
I tried to check for undefined in any way I could think of and I still get the same problem.
What I tried to check for undefined is this:
if(lastname === undefined || lastname === void 0 || typeof lastname == 'undefined') ...
I still get the toLowerCase of undefined error and I think that is why the job does not affect all of my user table since it stops...
Any suggestions?
So, I finally figured out why the job did not go through all the records but it would stop after a few records "randomly"...
I had an AfterSave hook for the user which was triggered at each iteration of the above job...
In that after save it would generate an error at times and make the Job fail.
So, for some reason I thought the after save hook would have not been triggered by a save done on the user while inside of a Job.
That's it. Now it all works.

My WebAPI2 service returns a JSON string, but $resource does not parse it

Here is my resource:
var app, deps;
deps = ['ngGrid', 'getUsers'];
angular.module('getUsers', ['ngResource'])
.factory('users', function ($resource)
{
return $resource('/Admin/GetUsers', {}, {
query: { method: 'GET', IsArray: true }
});
});
and then I've added code to try to add a step to force parsing:
$scope.myData = users.query(function(response)
{
if (typeof (response) == string)
{
response = JSON.parse(response);
}
});
But it never gets this far, and here's the error in Chrome:
Error: [$resource:badcfg] object
http://errors.angularjs.org/1.2.14/$resource/badcfg?p0=array
at http://localhost:23002/Scripts/angular.js:78:12
at a.module.factory.f.(anonymous function).p.then.m.$resolved (http://localhost:23002/Scripts/angular-resource.min.js:8:517)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at deferred.promise.then.wrappedCallback (http://localhost:23002/Scripts/angular.js:11046:81)
at http://localhost:23002/Scripts/angular.js:11132:26
at Scope.$get.Scope.$eval (http://localhost:23002/Scripts/angular.js:12075:28)
at Scope.$get.Scope.$digest (http://localhost:23002/Scripts/angular.js:11903:31)
at Scope.$get.Scope.$apply (http://localhost:23002/Scripts/angular.js:12179:24)
at done (http://localhost:23002/Scripts/angular.js:7939:45)
at completeRequest (http://localhost:23002/Scripts/angular.js:8142:7)
Of course I searched for that error, but I found advice to set IsArray to true or false, this makes no difference. If I set a breakpoint and call JSON.parse on the response string, it gets turned into an array of objects, exactly like what I want. So the string is perfectly valid JSON, but angular appears unwilling to parse it as such, it accepts it as a string and then dies.
My controller is very simple:
public List<ApplicationUser> GetUsers()
{
return AdminUsersViewModel.AllUsers;
}
and then, that method uses a LINQ query to get users from the DB, and then iterates over that collection to create a new one, because before I did that, it just blew up. I've made the call in the browser, and see the same string that is appearing in the angular code.
What I need to know is, why isn't angular spotting that this is a collection of objects, and how can I either force it to parse the string, or change the format so angular can tell what it is ?
Thanks for looking.
OK, I got it. I thought the help I read said to use IsArray ( in hindsight, I think it said DON'T use IsArray ). I knew that was non standard, but that's what I did. I ran the non minified version, and found my error. Change to isArray, and it works.
Thanks for looking :-)

Extjs store load success handler not getting fired

I have a store load method which returns data via an ajax request. I can see that the data is being returned using Firebug, but my success handler is not getting called:
this.getCategoriesStore().load({params:{'id':d.data.category_id}}, {
success: function(category) {
console.log("Category: " + category.get('name'));
},
error: function(e) {
console.log(e);
}
});
I am returning a success parameter, along with the data:
{"success":true,"categories":{"id":5,"name":"Frying","section_id":2}}
Is there something missing or am I doing anything wrong?
Well I suppose you are looking for this:
store.load({
params:{'id':d.data.category_id},
scope: this,
callback: function(records, operation, success) {
if (success) {
console.log("Category: " + category.get('name'));
} else {
console.log('error');
}
}
});
It is not that obvious in the API that your additional params can be placed there too. But ExtJS often uses the config objects to wrap things up.
Edit to answer comment:
The short answer is: Yes
Now the longer version:
In case of the store it is up to you to directly provide anonymous (or concrete) callbacks or register events. Both will work the same in your situation here.
But you can only have one callback while you can have many events. In further scenarios you will find situations where events fits much better or where events are the only way at all. That will always be the case when you are listening. Here are some notes on that:
make use of the { single: true } property when you just need a callback once. Example: store.on('load', function(s) { /* do something*/ }, scope, { single: true }) The listener will be removed after it was called. This is needed cause of the use of a anonymous function, that cannot be removed.
make use of mon() in most cases where you bind listeners directly in class-definitions to ensure the listeners get destroyed along with the instance of the class.
Both will save you browser memory.
Try this:
store.load({
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
http://docs.sencha.com/ext-js/4-1/#!/api/Ext.data.Store-method-load according to the docs there is no success and error callback.
Another alternative to providing callback you can also add a "load" event listener on the store for the same effect.

Extjs store.on('save', afterSave(resp));

I have a simple ExtJs (3.4) Grid with a Writer. When the user makes some changes the store is saved to the server as follows:
store.on('save', afterSave(resp));
All is fine. However, I want to get a response as to wheather the record has been saved successfully, failed or an update conflict happed. How to best do this?
Are you using Ext.data.proxy.Ajax to load your stores? If so, you can use the reader property to evaluate and handle the server responses.
Another option would be to make AJAX called directly and handle the responses from there as well
I used exception listener to parse the data as suggested here. But, is this the right way to do this.
Ext.data.DataProxy.addListener('exception', function(proxy, type, action,
options, res) {
if (type == 'response') {
var success = Ext.util.JSON.decode(res.responseText).success;
if (success) {
console.log('UPDATE OK');
} else {
console.log('UPDATE FAILED');
}
}
});

Resources