Can you overwrite a Firebase reference? - reference

I want to create a temporary reference such as:
var firebaseRef = new Firebase('httpX://reference.firebaseio.com/temp')
and then overwrite it once I receive a certain variable like this:
var firebaseRef = new Firebase('httpX://reference.firebaseio.com/variable')
When I try, the overwrite function seems to work at first: if I include
alert(firebaseRef)
in the function itself (after the overwrite attempt), it returns the new reference name but after the function runs, if I check firebaseRef again via console, it returns the old reference, and all subsequent calls go to the old ref.
Am I simply trying to do something not allowed by Firebase or am I doing it wrong?

Related

Triggering Google Cloud function using console

I am trying to use the google cloud console to test a cloud function. Below is a snippet.
exports.requestCreated = functions.firestore
.document('users/{userId}/requests/{requestId}')
.onWrite((change, context) => {
// execute operation
});
I have tried all sorts of combination of JSON data. E.g.
{"userId":"Xl86pqOpF9T2MAn12p24OJAfYJW2","requestId":"abc1234"}
But I keep getting the following statement in logs:
Request created by {userId}
The actual userId is not being read from the JSON data in the console. Can you help?
This is not a problem with the execution of the cloud function. It's a problem with hardcoding the string.
'users/{userId}/requests/{requestId}' is a hardcoded string. Node.js will not automatically replace {userId} with the value of the variable userId.
Following this previous SO post, try something like this using template strings:
`users/${userId}/requests/${requestId}`
Please note it is surrounded by backticks (`), not single quotes (').
This assumes you already have a userId and requestId variables defined. You must restructure your cloud function like this to retrieve that data. Notice that the specific variable values must be extracted from the event variable.
Thank you, Nareddyt. The function is for Firestore, and the way it is written right now checks if a new document is created under the collection requests. I tried replacing the string as you suggested, but as you pointed out, it requires these variables to be defined. I do not quite understand how to restructure the cloud function because the syntax I have used is how event detection is suggested in the Firestore documentation. My function currently works in its entirety, but testing it is a major pain. I have to go through my mobile app and do the whole userflow to test this function. I am new to Node.js and any guidance would be appreciated.

How to avoid performing a firebase function on folders on cloud storage events

I'm trying to organize assets(images) into folders with a unique id for each asset, the reason being that each asset will have multiple formats (thumbnails, and formats optimized for web and different viewports).
So for every asset that I upload to the folder assets-temp/ is then moved and renamed by the functions into assets/{unique-id}/original{extension}.
example: assets-temp/my-awesome-image.jpg should become assets/489023840984/original.jpg.
note: I also keep track of the files with their original name in the DB and in the original's file metadata.
The issue: The function runs and performs what I want, but it also adds a folder named assets/{uuid}/original/ with nothing in it...
The function:
exports.process_new_assets = functions.storage.object().onFinalize(async (object) => {
// Run this function only for files uploaded to the "assets-temp/" folder.
if (!object.name.startsWith('assets-temp/')) return null;
const file = bucket.file(object.name);
const fileExt = path.extname(object.name);
const destination = bucket.file(`assets/${id}/original${fileExt}`);
const metadata = {
id,
name: object.name.split('/').pop()
};
// Move the file to the new location.
return file.move(destination, {metadata});
});
I am guessing that this might happen if the operation of uploading the original image triggers two separate events: one that creates the directory assets-temp and one that creates the file assets-temp/my-awesome-image.jpg.
If I guessed right, the first operation will trigger your function with a directory object (named "assets-temp/"). This matches your first if, so the code will proceed and do
destination = bucket.file('assets/${id}/original') // fileExt being empty
and then call file.move - this will create assets/id/original/ directory.
Simply improve your 'if' to exclude a file named "assets-temp/".
According to the documentation there is no such thing as folders in cloud storage, however, it is possible to emulate them, like you can do by using the console GUI. When creating folders what really happens is that an empty object is created(zero bytes of space) but its name ends with a forward slash, also folder names can end with _$folder$ but it is my understanding that that is how things worked in older versions so for newer buckets the forward slash is enough.

In node.js, when I try to reference an array in a json file, it returns undefined

So I'm editing code right now, and I'm making a system that reads an array in a JSON file, and determines what to do if a user's id is in the array.
So, I put const idarray = require('./config.json').idarray
if (idarray.includes("1234")) return console.log(idarray);
So, it should return the contents of the array, right? Well no, it doesn't. It returns 'undefined', and crashes. Could I get some help? I've used this multiple times before, and it hasn't errored once...

CoffeeScript Preserve Multiple `this` objects?

I'm in a rather unique situation (one I've never found myself in before) and I can't find anything on how it should be handled, so I thought I'd ask here. (and perhaps start a good discussion on how it should be handled)
I'm writing a Node.js/Express application that does a series of database calls in various route handlers. I'm using the node-sqlite3 module to make the database calls. In this case the user is uploading a file, so I take that from the form POST data and save it to the filesystem (will be moved to blob storage later) and generate some xml files for other reasons. The way that I name these files is by the id in the database to facilitate routes like '/file/:id' to GET the file later on, as well as leveraging the database to ensure I don't have name collision issues.
I'm doing this in CoffeeScript so I'm wrapping this model in a class, so it uses this (or #) to access these helper methods. Before I was doing a last_insert_rowid() call to get the id of the thing I just inserted but this opens me up to potential race conditions. So as it turns out when you do an INSERT in the node-sqlite3 module the callback it calls when it's done saves the last inserted row id in the this object (so (err) -> fileid = #.lastID). Now for some code (names changed and simplified).
uploadFile: (fileData, cb) ->
#.openConnectionIfClosed()
#db.serialize =>
# preserve the # object to allow calls to class methods like #.saveFile
#db.run 'insert into thing (val=$val)', $val: 'some_val', (err) ->
if err
cb err
return
# # refers to the this object provided by #db.run
fileid = #.lastID
async.waterfall [
(async_cb) =>
# uh oh, the # object is the one from the db library, not my class
# earning me a 'method undefined' error
#.saveFile fileid, async_cb
# etc... you get the idea
...
], (err) -> cb err
#.closeConnection()
So I'm needing to retain the class this object to access instance methods, but I also need to get the lastID value out of the this object returned by default from the callback in the db call. Obviously if I change the callback on the db call to fat arrows I can access my class methods, but then the #.lastID returns undefined.
What's the "proper" way to achieve this? (in CoffeeScript or JavaScript, doesn't particularly matter) I think that the way I can solve this is by assigning a context variable like ctxt = # at the top of the method but obviously this isn't favorable. Any ideas?
EDIT: Oh, and I forgot to mention, I can't just name the file something else because I also need that id to update the database. The call to async.waterfall does: Save file -> generate xml metadata file & save it -> add the path of the xml file to the database entry retroactively. Though I could potentially use a statement to do that without completely isolated database calls, haven't investigated that yet.
In JavaScript, if you need to preserve a particular context, its standard practice to use the variable self, as such:
var self = this;
In CoffeeScript, the fat arrow is standard practice for cases like this, though using 'self' is not wrong either.

Where to initialize extension related data

am a newbie, trying to write some basics extension. For my extension to work i need to initialize some data, so what I did is inside my background.js i declared something like this.
localStorage["frequency"] = 1; //I want one as Default value. This line is not inside any method, its just the first line of the file background.js
Users can goto Options page and change this above variable to any value using the GUI. As soon as the user changes it in UI am updating that value.
Now the problem is to my understanding background.js reloads everytime the machine is restarted. So every time I restart my machine and open Chrome the frequency value is changed back to 1. In order to avoid this where I need to initialize this value?
You could just use a specific default key. So if frequency is not set you would try default-frequency. The default keys are then still set or defined in the background.js.
I like to do that in one step, in a function like this
function storageGet(key,defaultValue){
var item = localstorage.getItem(key);
if(item === null)return defaultValue;
else return item;
}
(According to the specification localstorage must return null if no value has been set.)
So for your case it would look something like
var f = storageGet("frequency",1);
Furthermore you might be interested in checking out the chrome.storage API. It's used similar to localstorage but provides additional functionalities which might be useful for your extension. In particular it supports to synchronize the user data across different chrome browsers.
edit I changed the if statement in regard to apsillers objection. But since the specification says it's ought to be null, I think it makes sense to check for that instead of undefined.
This is another solution:
// background.js
initializeDefaultValues();
function initializeDefaultValues() {
if (localStorage.getItem('default_values_initialized')) {
return;
}
// set default values for your variable here
localStorage.setItem('frequency', 1);
localStorage.setItem('default_values_initialized', true);
}
I think the problem lies with your syntax. To get and set your localStorage values try using this:
// to set
localStorage.setItem("frequency", 1);
// to get
localStorage.getItem("frequency");

Resources