Hey there StackOverflow people of the world! Thank you for helping me with my question, and I apologize if this question gets a bit long winded. I just want to be clear about all the details and constraints I am working with. I found a few other related questions but nothing that was really very clear about how to get around my specific problem, unless I am missing something. Related questions:[1, 2]
Question Setup:
This is what I have and how it works, my question will be about a problem I am having
I've got a object that I've filled with named functions. The purpose of the object map is to contain many functions calls from multiple files. I am calling each function a "business rule" and they are typically very small functions that do a singular action with well-defined inputs and outputs. It also lets me chain the function calls sequentially with the output from functionCall1
becoming the input functionCall2
.
All of my business rule definitions up to this point have been in a set of files that reside in a sub-folder called "Framework", but what I am trying to do now is allow the "Client" to define their own business rules in their own files and their own object map of function calls. What I would like to do is add all of the function calls to a single shared data storage.
What I am trying to avoid doing: I am NOT trying to serialize the function calls, neither am I trying to leverage the 'eval' capability of JS. I've tried working with this before and it gets really messy! Also I DO NOT want to declare a "class" object or use the "this" keyword for this reason: 10-most-common-javascript-mistakes
What is working: (NOTE: Greatly simplified as I currently have hundreds of "business rules")
// rulesLibrary.js
import * as stringParsing from './Rules/stringParsing';
export const rulesLibrary = {
['Echo']: (inputData, inputMetaData) => (inputData, inputMetaData),
// Business Rules
// ********************************
// StringParsing rules in order
// ********************************
['stringToBoolean']: (inputData, inputMetaData) => stringParsing.stringToBoolean(inputData, inputMetaData),
['stringToDataType']: (inputData, inputMetaData) => stringParsing.stringToDataType(inputData, inputMetaData),
}
// stringParsing.js
export const stringToBoolean = function(inputData, inputMetaData) {
var returnData;
// Function Body...
return returnData;
};
export const stringToDataType = function(inputData, inputMetaData) {
var returnData;
// Function Body...
return returnData;
};
// ruleBroker.js
import * as rules from './rulesLibrary';
export const processRules = function(inputData, inputMetaData, rulesToExecute) {
var returnData = inputData;
for (var rule in rulesToExecute) {
if (rulesToExecute.hasOwnProperty(rule)) {
var key = rule;
var value = rulesToExecute[key];
returnData = rules.rulesLibrary[value](returnData, inputMetaData);
}
}
return returnData;
};
You can see in the code above the rulesLibrary
is defining the functions in an object rulesLibrary = {};
which is also exported. Then in the ruleBroker
we are calling the associated function:
rules.rulesLibrary[value](returnData, inputMetaData)
....and this works great.
My Goal
My goal is to rather than store all these functionName: functionCall
on the rules.rulesLibrary
, I want to store them on a singleton data storage object I am calling "D"
.
Here is the definition of "D":
// data.js
export var data = {};
What I have tried - Attempt 1
I first tried to assign all of the contents of the rules.rulesLibrary
from the rulesLibrary.js
directly to "D"
like so in the ruleBroker.js
file:
// NOTE: I am actually doing this inside a function so I can boot-strap the rules.rulesLibrary into `D`, before the application begins going about the business of calling business rules via the ruleBroker.
import * as rules from './rulesLibrary';
var D = require('../Resources/data');
D['BusinessRules'] = {};
D['BusinessRules'] = rules.rulesLibrary;
This did not work and attempting to console.log(JSON.stringify(D));
just gave me back:
D{BusinessRules} = {};
What I have tried -- Attempt 2
So I thought maybe I should try and define the business rules map named function calls directly on "D"
like so in the rulesLibrary.js
file:
// NOTE: I am again doing all of this inside a boot-strap function for the same reason as above.
export const initRulesLibrary = function() {
D['BusinessRules'] = {};
D['BusinessRules'] = {
['Echo']: (inputData, inputMetaData) => (inputData, inputMetaData),
// Business Rules
// ********************************
// StringParsing rules in order
// ********************************
['stringToBoolean']: (inputData, inputMetaData) => stringParsing.stringToBoolean(inputData, inputMetaData),
['stringToDataType']: (inputData, inputMetaData) => stringParsing.stringToDataType(inputData, inputMetaData),
}
};
Again I get the same thing, contents of D
are: D{BusinessRules} = {}
.
Maybe console.log
in combination with JSON.stringify
doesn't work with function-objects?
But then again, I do have rules that return a function-object and I have been able to stringify those function-objects in the past with this same code. Granted it's a function-object so I am not expecting it to look pretty when stringified, but that's not the point. The point should be that the function-object exists on 'D' and it clearly does not, what am I missing here? How can I get all my function-objects mapped on 'D' so that I can add/merge more function-object definitions to it?
Ultimately this is what I want to be able to do:
function addClientRules(clientRules) {
Object.assign(D['BusinessRules'], clientRules['BusinessRules']);
};
Such that D
now contains all of the system-defined business rules & all of the client defined business rules. Then in the ruleBroker
, I would just call whatever business rule like this:
export const processRules = function(inputData, inputMetaData, rulesToExecute) {
var returnData = inputData;
for (var rule in rulesToExecute) {
if (rulesToExecute.hasOwnProperty(rule)) {
var key = rule;
var value = rulesToExecute[key];
// OLD WAY:
// returnData = rules.rulesLibrary[value](returnData, inputMetaData);
// NEW WAY:
returnData = D['BusinessRules'][value](returnData, inputMetaData);
}
}
return returnData;
};
Any ideas? Thoughts? Edits? Rants? Am I at least on the right track?
Thank you again for your help! Hopefully this will help someone else too!! :-D