drive realtime api model toJson not populating fields in custom type - google-drive-realtime-api

I'm building a Drive Realtime project using custom types: https://developers.google.com/google-apps/realtime/custom-objects.
I'm having an issue where the fields in my custom objects are not exported in the model.toJson() output. I'm sure I'm just missing something, but I haven't been able to find any differences with how I'm constructing the custom object vs. the realtime playground or the realtime API documentation.
Sample repro case using the realtime playground is below.
1) go to realtime playground: https://realtimeplayground.appspot.com/
2) open developer console
3) Run the following code
test = function () {}
test.prototype = { init: function() { this.name = 'testName';}};
test.prototype.name = gapi.drive.realtime.custom.collaborativeField('name');
gapi.drive.realtime.custom.registerType(test, 'testType')
gapi.drive.realtime.custom.setInitializer(test, test.prototype.init);
var model = window.doc.getModel()
model.getRoot().set('myTest', model.create(test));
model.toJson()
observed output:
"{"id":"root","type":"Map","value":
{"demo_string":
{"id":"Tq50c9iybcXi","type":"EditableString","value":"Edit Me!"},
"demo_list":{"id":"ZmjclOeUbcXj","type":"List","value":
[{"json":"Cat"},{"json":"Dog"},{"json":"Sheep"},{"json":"Chicken"}]},
"demo_cursors":{"id":"6TJ6Zzd2bcXj","type":"Map","value":{}},
"demo_map":{"id":"ukRRMPHbbcXj","type":"Map","value":
{"key1":{"json":"value 1"},"key2":{"json":"value 2"},"key3":{"json":"value 3"}}},
"demo_custom":{"id":"44nsuMAPbcXk","type":"DemoMovie","value":
{"name":{"json":"Minority Report"},
"director":{"json":"Steven Spielberg"},
"notes":{"json":""},"rating":{"json":""}}},
"myTest":{"id":"Kq4hcV4UbcvW","type":"testType","value":{}}}}"
Expected:
"{"id":"root","type":"Map","value":
{"demo_string":
{"id":"Tq50c9iybcXi","type":"EditableString","value":"Edit Me!"},
"demo_list":{"id":"ZmjclOeUbcXj","type":"List","value":
[{"json":"Cat"},{"json":"Dog"},{"json":"Sheep"},{"json":"Chicken"}]},
"demo_cursors":{"id":"6TJ6Zzd2bcXj","type":"Map","value":{}},
"demo_map":{"id":"ukRRMPHbbcXj","type":"Map","value":
{"key1":{"json":"value 1"},"key2":{"json":"value 2"},"key3":{"json":"value 3"}}},
"demo_custom":{"id":"44nsuMAPbcXk","type":"DemoMovie","value":
{"name":{"json":"Minority Report"},
"director":{"json":"Steven Spielberg"},
"notes":{"json":""},"rating":{"json":""}}},
"myTest":{"id":"Kq4hcV4UbcvW","type":"testType","value":{"json":"testName"}}}}}"

Registering custom types can only occur during the "Pre-Load" phase of the document life cycle. Your code is correct, but is being executed on the document after the document has loaded. This causes the custom object to not be properly constructed, which is why it is lacking the JSON value that you have specified in the init function.
To see the correct flow in action, put a break point on line 88 of static/elements/playground-app.js in the Realtime Playground application. Refresh the page and when execution has paused, run this code from the console:
test = function () {}
test.prototype = { init: function() { this.name = 'testName';}};
test.prototype.name = gapi.drive.realtime.custom.collaborativeField('name');
gapi.drive.realtime.custom.registerType(test, 'testType')
gapi.drive.realtime.custom.setInitializer(test, test.prototype.init);
Resume execution. When the application has fully loaded, run the rest of your code:
var model = window.doc.getModel()
model.getRoot().set('myTest', model.create(test));
model.toJson()
You will see that the outputted JSON matches what you are expecting:
"myTest":{"id":"1OiQd2QoEqBs","type":"testType","value":{"name":{"json":"testName"}}}
This workflow is documented under the "Registering custom types and fields" title of the Custom Collaborative Objects guide.

Related

React Remote Console Logging

I setup an Express Server with Mongo to record console logs during debug testing of an Electron app using React.
I simply use ajax to send what I would normally print with console.log. This works fine with individual events I want logged, but how do I export the entire chrome style console as an object so that anything that would reach the console (example: webpack messages, messages from other components etc) would all be accessible as one object that I can do a POST on.
Basically a way to record everything that you would see in the console whether it was from a 3rd party package or that I expressly logged myself. Is there a console dump all method of some sort I'm not seeing in the chromium/electron/react docs?
example:
//import some debugger method to POST to server collecting logs
export function debugpost(logobject) {
$.ajax({
type: "POST",
url: "http://" + "192.168.0.94" + ":3000/tasks",
headers: {
},
data: {
log: logobject
},
success: function(data) {
}.bind(this),
error: function(errMsg) {
console.log(errMsg);
}.bind(this)
});
}
//simple way of recording logs in other component.
var testlogmessage = "This isn't right"
debugpost(testlogmessage);
Logging individual events to the server is easy. How do I dump the entire console?
UPDATE
Mentioned below was to tie into the process stdout and stderr. I tried the recommended package capture-console and also this code snippet:
var logs = [],
hook_stream = function(_stream, fn) {
// Reference default write method
var old_write = _stream.write;
// _stream now write with our shiny function
_stream.write = fn;
return function() {
// reset to the default write method
_stream.write = old_write;
};
},
// hook up standard output
unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
logs.push(string);
});
However both give me this error with write when using with react:
TypeError: Cannot read property 'write' of undefined
hook_stream
That particular method seems to log the electron node side fine when I use it in the electron main.js. However I can't get it to work within my react components.
One way of doing this is to overwrite the console.log with your custom implementation, so whenever any part of the code calls the console.log the call will be intercepted by your custom function where you can log the message to your remote server using some API calls.
Once you have logged your message you can call the original console.log method.
Following example shows a custom implementation of console.log method.
var orgLog = console.log;
console.log = function(message) {
alert("Intercepted -> " + message); //Call Remote API to log the object.
//Invoke the original console.log
return orgLog(message);
}
let a = {
foo: "bar"
};
console.log(a);
You tie into the stdout, stderr streams in the process module.
Take a look at npm capture-console. You will need to capture console output from any renderer process as well as the main process.
UPDATE
It appears electron has done some strange things with renderer process stdout stream. You are better off using a custom logging solution like electron-log and syncing logs from the written log file.

how to query sails-disk in sailsjs

I have generated the api in sailsjs using
sails generate api testAPI
and I have been able to create data using the command
http://localhost:1337/testAPI/create?username=f1&password=123
and i can get the result
but when I want to customize the route
for get - http://localhost:1337/testAPI/1
i am using the code
module.exports = {
findOne:function(req,res){
res.ok('overridden');
}
};
in testAPIController.js for the overriding
and when I go the route http://localhost:1337/testAPI/1 I am able to see overriden displayed there.
but how do I query the data and show a customized view there?
to customize and query the data I am using this code and it doesnt work
says that testAPI not defined
module.exports = {
findOne:function(req,res){
var results = testAPI.find()
res.ok(results);
}
};
so, what am I doing wrong here?
The model you created should be used with the first capital letter (TestAPI.find());
Also, you should consider the assync factor when fetching data. See code bellow
module.exports = {
findOne:function(req,res){
TestAPI.find().then(function(results) {
return res.ok(results);
});
}
};

Trying to get ng-csv to work with Firebase

I have data stored on Firebase. I have a function that will grab the information from Firebase and return it as an array. I want to be able to use ng-csv to download that file as a .csv however when I download it is an empty file.
Is it possible to use ng-csv if I am trying to grab data from Firebase and if so does anyone have any examples?
Update (from OPs duplicate question):
I am trying to use ng-csv to allow a user to download a .csv file by clicking a button. The information is stored in Firebase and I have created a function that returns the needed information from Firebase as an array. However, I think the problem is when the button is clicked the file is downloaded before the information is pulled from Firebase and loaded, so the .csv file is always empty. Is there a way around this? Here is my code in my main.js app:
this.export = function() {
var results = fireFactory.getResults() //code that returns the array of objects
results.$loaded().then(function(array) {
var test= [];
test.push(array[0]);
test.push(array[1]);
return test;
};
};
Here is my code in my HTML file:
<button class ="btn" ng-csv="main.export()" filename="test.csv">Export</button>
Is there anyway to delay the file downloading until the information has been loaded and returned from the main.export() function?
You are almost there. Frank van Puffelen was on the right path, but stopped short of providing the fix for your code.
return test;
the above statement inside your callback is returning the result inside a promise. This results can only be consumed using promise aware code. Fortunately, ng-csv accepts a promise. If the promise is returned it should work:
this.export = function() {
var results = fireFactory.getResults()
//Here we return the promise for consumption by ng-csv
return results.$loaded().then(function(array) {
var test= [];
test.push(array[0]);
test.push(array[1]);
//the array is returned from the callback, not export
return test;
};
};
You're being tricked by the asynchronous nature in which Firebase loads data. You seem to be thinking that return test; in your original code returns a value from the export function. But if you look more carefully you'll notice that you're actually returning from the (anonymous) callback function.
It's a bit easier to see this, if we separate the callback function out and add some logging statements:
function onDataLoaded(array) {
console.log('Got results from Firebase');
var test= [];
test.push(array[0]);
test.push(array[1]);
return test;
};
this.export = function() {
console.log('Starting to get results from Firebase');
var results = fireFactory.getResults() //code that returns the array of objects
console.log('Started to get results from Firebase');
results.$loaded().then(onDataLoaded);
console.log('Registered result handler');
};
When you call fireFactory.getResults() Firebase will start downloading the data from its servers. Since this may take some time, the downloading happens asynchronously and the browser continues executing your export function, which registers a callback that you want invoked when the data from Firebase is available.
So you'll see the following output in the JavaScript console:
Starting to get results from Firebase
Started to get results from Firebase
Registered result handler
Got results from Firebase

Yelp API key not working in Sencha Architect demo code

I am using the tutorial here : http://docs.sencha.com/architect/3/tutorials/first_mobile_application.html#The_Controller
getBusinesses: function(location, callback) {
// Note: Obtain a Yelp API key by registering (for free)
// with Yelp at http://www.yelp.com/developers/getting_started/api_overview
// (in this app, we use the Review Search API v1.0)
var store = Ext.data.StoreManager.lookup('BusinessStore'),
yelpKey = '', // Enter your Yelp API key here
url = 'http://api.yelp.com/business_review_search' +
'?ywsid=' + yelpKey +
'&term=Bars' +
'&lat=' + location.coords.latitude +
'&long=' + location.coords.longitude;
store.getProxy().setUrl(url);
store.load(function() {
callback(store);
});
}
I applied for an API key on Yelp and got the following:
I am not sure which one to use. The tutorial code has placeholder for one single key as in the code above
The completed app shows error: Uncaught TypeError: Cannot read property 'setStore' of undefined at:
me.getBusinesses(location, function (store) {
// Bind data to the list and display it
me.getDataList().setStore(store);
You need the API v1.0 key.
getDataList() returns undefined because the View does not exist. You may have forgotten to name the List view in the ListContainer, see "List View - Step 4". Also, the function name is derived from whatever you set the reference to in *"The Controller - Step 7". Naming it datalist will make the function getDatalist(), whereas naming it dataList will make it getDataList(). Note the capital "L".
Hope this helps others running into the problem.

AngularFire equivalent to $setPristine?

I'm trying to understand the correct workflow to create a $setPristine equivalent with my Firebase data.
My workflow is as follows:
1) Create Firebase object (via the Angularfire Generator 'SyncData')
2) Form data modifies the $firebase object.
3) To update the remote model, I use myRef.$save()
All of that works well. Now, I'm trying to add a "reset" button on the form, so that the locally modified data will revert back to the remotely stored data.
So far, I'm running into problems. I've tried reinitializing the firebase reference eg myRef = syncData('/my/path') but not only does that now work, but it is destroying the remote data object!
What is the correct way to re-pull the remote data to use in my Angular model?
I know this is an old question, but I ran into this issue myself.
After some searching around I found this post: http://grokbase.com/t/gg/firebase-angular/1499haaq4j/editing-data-as-a-copy
Which led me to an outdated code snippet (2 months lol XD) from #Kato: https://gist.github.com/katowulf/8eaa39eab05a4d975cd9
I modified this to work with Firebase 2.3.1 and AngularFire 1.1.3:
app.factory('ResetFactory', function($firebaseArray) {
return $firebaseArray.$extend({
reset: function(itemOrIndex) {
var key, self;
self = this;
key = self.$keyAt(itemOrIndex);
self.$ref().child(key).once('value', function(snap) {
self.$$updated(snap);
});
}
});
});
Which can be called via:
var comments = new RevertFactory(ref.child('comments'));
# variable comment is for example an ng-repeat that's being edited
comments.reset(comment);

Resources