Sequelize.fn : Constructing the update argument outside the call - javascript

Issue Description
I'm currently trying to make updates on passwords using sequelize.fn.
I've seen numerous sites, including the Sequelize's manual, yet I found too few articles that approaches my case, and none of them seems to solve it.
Moreover, the function to encrypt the passwords need nested function, so I need to gradually construct the nested function
by putting the successive arguments into variables.
I have not found anything on constructing the functions, thus using sequelize.fn outside the arguments of the functions find and updates.
Additional context
In my case, " crypt('password', gen_salt('bf', 4)) " (in Postgres) needs to become
sequelize.fn('crypt', 'password', sequelize.fn('gen_salt', 'bf', 4)) and to be stored into a variable
When I inject it into the update function, an Fn Object is injected, and the result in the database seems to be a memory address instead of the result of the crypt function.
I may post a code example so you can have a better understanding of what I'm trying to do and I think should be added into the documentation
I did not made this doc issue to resolve my issue, only to point out what I think is lacking in the documentation
I will ask StackOverflow for help regarding my issue.
//Take a format and a value, and applies the functions inside the format onto the value
function recursSequelizeFn (format, value) {
const sequelize = db.sequelize;
let nextId = 0;
let matches;
let finalArgs = {};
//The RegEx finds the function calls of which parameters aren't functions themselves
//As the format string is modified on each loop, I need to initialize the RegEx on each loop
while ((matches = (/(\w+)\(([^(,)]+)?(?:,([^(,)]+))*\)/g).exec(format)) !== null) {
//matches[0] is the whole expression
//matches[1] is the function's name
//matches[>=2] are the arguments
let func = matches[1];
let args = matches.slice(2);
for (let argNo in args) {
//Transforms DB's columns into Sequelize-interpreted columns
//I do not check the column that is found, because I do not have others columns than the one that is being treated
args[argNo] = args[argNo].replace(/seqCol_(\w+)/g, (correspondance, p1, decalage, chaine)=>{return value;});
//If the parameter was previously saved, we replace its reference by its value
args[argNo] = args[argNo].replace(/(#\d+)/g, (correspondance, p1, decalage, chaine)=>{return finalArgs[p1];});
}
//finally, we save the value of the function and replace the whole expression by a reference
finalArgs['#'+nextId]=sequelize.fn(func, ...args);
format = format.replace(matches[0], '#'+nextId);
nextId++;
}
//When the treatment is finished, we return the last value saved into the array
//Or we return the original value if we have not made any change (the array will be empty)
return finalArgs['#'+(nextId-1)]||value;
}
Object.keys(req.message.attributes).map((key)=>{
//req.message.attributes[key] contains the formatting needed to be put onto the value
//e.g. crypt(password, gen_salt('bf', 4))
//req.body[key] contains the value
//e.g. '1234'
let seqValue = util.recursSequelizeFn(req.message.attributes[key], req.body[key]);
req.body[key] = seqValue;
});
//mainModel is a sequelize model
mainModel.update(req.body, {where: {id:req.params.id}, logging:console.log})
.then() //...

Related

Is it possible to get result variable name inside function?

I want to get variable name(user_name1 or user_name2 from sample) which is get result of a function(GetUserName()) inside this function(GetUserName()). I need this name for create object with the same name on server side(data synchronization).
function GetUserName(){
let result_variable_name = ????; //in (1) result_variable_name == 'user_name1', in (2) result_variable_name == 'user_name2'
socket.send("object_name", result_variable_name);
return "Some user name";
}
let user_name1 = GetUserName(); //(1)
let user_name2 = GetUserName(); //(2)
Is it possible? How?
No. Just no. Variable names should have no intrinsic meaning. They're just placeholders in an algorithm, and sometimes you can't even control their names to the extend you need. Also, the variable doesn't really exist yet at the time you call the function. And even if it did, there's no sane way to figure out what variable the result of the function will be assigned to from within said function.
Also:
let users = [GetUserName(), GetUserName()];
Now what?
Pass the name explicitly into the function, period.
GetUserName('user_name1')

failing using call by reference to take the function return object value

Now I implement a function of finding users in user groups. These are nested groups, so the search is realized by recursive calls. My codes are listed bellow; I also use redux.
I use searchGroupUserAcc to call search to get the target group that contains the specified user. I've confirmed that the parameter targetGroup is assigned correctly, but I don't know why its value is still {} after the search is done.
I am very confused; all ideas are welcome. Thanks.
function search(groups)(groups, tokenAcc, targetGroup){
...
//search in a group; g is one group is groups
for(let i=0;i<g.userList.length;++i) {
if(g.userList[i]===tokenAcc) {
//confirmed that targetGroup's value is not{}
targetGroup=JSON.parse(JSON.stringify(g));
return;
}
}
//for searching subGroups
search(...);
}
//tokenAcc is the user account key used to search in the group array.
export function searchGroupUserAcc(tokenAcc){
return (dispatch)=>{
...
let targetG={};
//use tokenAcc to search in groups. every group in groups contains the useraccount info
//expect targetG to hold the return value.
search(tokenAcc, groups,targetG);
console.log(targetG);//still prints{}, but why
};
}
Why don't you return the value from your search function directly?
if(g.userList[i]===tokenAcc) {
return JSON.parse(JSON.stringify(g));
}
and then in your second function: targetG = search(tokenAcc, groups,targetG);
EDIT
Given that you are using redux, I would highly suggest you move to a more functional and pure approach, which, among other things, implies that you avoid side effects (i.e. what you are doing right now) and always use the return value of a function. Have a look at the official redux documentation for more information about it
Hy Buddy.
Javascript is always pass by value, but when a variable refers to an object, the "value" is a reference to the object.
So if you changing the value of a variable never changes the underlying primitive or object, it just points the variable to a new primitive or object.

How to set a localStorage item as function?

I would like to set a localStorage item as a function, but when I do it gets saved as a string.
localStorage.getData = function (key="def") {
let data = null;
if (this[key] && !_this.isDataAvailableInList(this[key])) {
data = this[key].data;
}
return data;
};
The above function get stored as string and not function.
Note: Kindly do not provide alternatives or other suggestions, I am well aware of alternatives and am curious to know how this works. I have not provided the entire context so lets just assume I am in need of setting a localStorage item as a function
Unfortunately local storage is only about strings. Even arrays or other data are always converted to strings.
For most dead data without cycles you can use of course JSON.stringify and JSON.parse, but in other cases or for code or other Javascript entities unsupported by JSON (like Infinity or undefined) you need to serialize and deserialize yourself.
Javascript provides eval, so you can store the function f converting it first to a string with f+"" and get back the function with eval(s).
This won't work with closures however and moreover you cannot even know if a function is indeed a closure or not in Javascript (so you cannot even raise an error if the impossible operation of serializing a closure is attempted).
Convert the function into a string via .toString(). When you read it, convert it back to a function via new Function(myString).
Example:
No pamameters:
(new Function('var a = 0; return a + 1;'))() === 1
With parameters:
(new Function(['param0'],'var a = param0; return a + 1;'))(100) === 101
Note: The scope of the original function will be lost.

Javascript push() replacing element instead of appending

Here's a function I have written to add words to local storage using Javascript. In case you're wondering, this is my attempt at building a search history functionality for a simple dictionary lookup site.
function add2local(entry){
var l = localStorage.length;
if(l==0){
var lu = [entry];
localStorage.setItem("w", JSON.stringify(lu));
}
else {
var lu = JSON.parse(localStorage.getItem("w")); alert(lu);
lu.push(entry); alert(lu);
}}
My understanding is the this function would keep appending its argument to local storage every time it's called. So, the first time I call it, I send it the word pirate. This gets added to the array and subsequently to the local storage as expected. The first alert() (the alert() functions are solely being used for testing) confirms this. The second time, I call it with the word vampire. Now, going by the function's logic, vampire should be appended to the array and thus the second alert() should output "pirate, vampire." And so it does.
But the third time around, say, I call the function with the word foo. This time around, it should output "pirate, vampire, foo" but instead shows "pirate, foo". Every subsequent call simply replaces the second word with the new word instead of appending it. What might I be doing wrong here? Am I misunderstanding how push() works?
The if condition and logic is incorrect; it is irrelevant how many items localStorage has, but it is very important to re-save the modified array.
In any case, I suspect an impl. might look as so:
function add2local(entry){
// load entries - if there are none, we simulate an empty array to load
var lu = JSON.parse(localStorage.getItem("w") || "[]");
// add new entry
lu.push(entry);
// write back - so change is not lost between function calls
localStorage.setItem("w", JSON.stringify(lu));
// return all local entries saved - for use from the caller
return lu;
}
Why check the storage length? You don't care. Fetch the key and if it's null then default to empty array.
function add2local (entry) {
var key = "w"
var value = localStorage.getItem(key)
if (value) {
value = JSON.parse(value)
} else {
value = []
}
value.push(entry)
localStorage.setItem(key, JSON.stringify(value))
}

Object literal multiple assignment in CoffeeScript

I'm a bit of a newbie in Javascript. I was looking through a bit of Coffeescript code for an Atom package, and I stumbled upon this piece of code:
loadProperties: ->
#properties = {}
fs.readFile path.resolve(__dirname, '..', 'completions.json'), (error, content) =>
{#pseudoSelectors, #properties, #tags} = JSON.parse(content) unless error?
return
I was a bit confused by the last line {#pseudoSelectors, #properties, #tags} = JSON.parse(content) unless error? because it seems like it assigns multiple values from the parsed JSON content. In my confusion, I decided to convert this back to Javascript using js2Coffee, and I ended up with the following:
function() {
this.properties = {}; // make list of properties (global to provider)
return fs.readFile(path.resolve(__dirname, '..', 'completions.json'), (function(_this) { //load completions.json (using path module)
return function(error, content) { // edit: nvm, js2coffee's fault. not sure why they wrapped the call back in another anonymous function, but this is a node stream callback
var ref;
if (error == null) { // if there are no errors
ref = JSON.parse(content), _this.pseudoSelectors = ref.pseudoSelectors, _this.properties = ref.properties, _this.tags = ref.tags;
}
};
})(this));
This code is a bit more understandable than the above. I can see that ref is assigned the object parsed from the content stream, and is then used to assign the other variables with their designated data. My question is, how does this type of assignment work? In Coffeescript, how does the preprocessor know where to assign the values, and in what order to assign them in?
By inspecting completions.json, the data is not in the order in which the assignments occur.
This is known as Destructuring Assignment.
To make extracting values from complex arrays and objects more convenient, CoffeeScript implements ECMAScript Harmony's proposed destructuring assignment syntax. When you assign an array or object literal to a value, CoffeeScript breaks up and matches both sides against each other, assigning the values on the right to the variables on the left.
CoffeeScript interprets an object or array on the left side of an = as a pattern, matching the names used...
#pseudoSelectors
#properties
#tags
...to properties or indices within the value being assigned:
JSON.parse(content).pseudoSelectors
JSON.parse(content).properties
JSON.parse(content).tags
(Defining the additional ref to avoid reevaluating JSON.parse(content) for each.)
As for order, CoffeeScript will generally use the order they're mentioned within the assignment. Moving #pseudoSelectors to the 3rd property in the pattern will be echoed in the generated JavaScript.
{#properties, #tags, #pseudoSelectors} = JSON.parse(content) unless error?
var ref;
if (typeof error === "undefined" || error === null) {
ref = JSON.parse(content),
this.properties = ref.properties,
this.tags = ref.tags,
this.pseudoSelectors = ref.pseudoSelectors; // now last
}
Though, JavaScript Objects, like the result of JSON.parse(content), aren't enforced as sorted data structures. If you need to ensure the order of the values, you'll have to instead use an Array.

Categories