How to collect values for multi-valued queryparam in apigee? - apigee

For a request with a multi-valued queryparam like: https://test.apigee.net?storeIds=abc&storeIds=xyz, how can someone setup an extract variable policy so that there will be a storeIds array like: storeIds=["abc","xyz"]?
Update #1:
Using the following in javascript for Apigee:
var arrayOfStoreIds = [];
for (i = 0; i < context.proxyRequest.queryParams['storeIds'].length; i++) {
arrayOfStoreIds.push(context.proxyRequest.queryParams['storeIds'][i]);
}
Yields an error:
`Execution of script failed with error:
Javascript runtime error:
"TypeError: Cannot find default value for object ... at line ##"`
The line # referenced points to the 1st line of the for loop
Update #2:
Incorrect documentation at http://apigee.com/docs/api-services/reference/javascript-object-model:
context.proxyRequest.queryParams['city'].length; // == 2
Correct syntax at https://github.com/ap-andrew/DevGuide/blob/master/javascript_new.html#L141
context.proxyRequest.queryParams['city'].length(); // == 2
So with this context.proxyRequest.queryParams['storeIds'].length() it works! At least in javascript ... I still don't know how to do this via an extract variable policy...

Truth be told, there is no spec on using duplicate query parameters. However, you can clearly see there's an issue when trying to retrieve them; you'd encounter this in php using $_GET, in JavaScript, Node.js, et al.
I'd suggest if you can, do something using pipe or comma separation: storeIds=abc,xyz. Then to extract query parameters using an ExtractVariables policy, you would do something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ExtractVariables async="false" continueOnError="true" enabled="true" name="productsVariables">
<DisplayName>Extract</DisplayName>
<URIPath>
<QueryParam name="storeIds">
<Pattern ignoreCase="true">{storeIdsArray}</Pattern>
</QueryParam>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>
In your javascript, you could then do:
try {
var storeIdsArray = context.getVariable('storeIdsArray').split(',');
storeIdsArray.forEach(function(storeId) {
// do something with storeId
}
}
catch (e) {
// storeIdsArray wasn't defined or not an array or something else went wrong
}

In raw CGI you can split multiple values with the same queryparam on NULL, but in Apigee, by the time it gets to the Message Processor, the queryparam only contains the first value. So the only way to do this is brute force using the full message.querystring.
If I sent in:
testme?myQueryParam=Y&myQueryParam=X
I have to do a double split using JavaScript and loop through each queryparam doing something like this:
var text = "";
var myQueryParams = context.getVariable('message.querystring');
var myQueryParamArray = myQueryParams.split(/\&/);
for (i = 0; i < myQueryParamArray.length; i++) {
var myvals = myQueryParamArray[i].split(/\=/);
text += myvals[1] + ", ";
}
context.setVariable('mytext', text);
In this example I create a variable named mytext with the value of "X, Y,"

Related

Using non-scalar variables in BuildMaster otter-script plans

I'm pulling my hair out trying to get some very basic iteration working using non-execution set variables (ie setting things at Global with potential to override at lower scope).
Setting a $variable to some value works fine but I need to do something like...
foreach $DeployConfigKey in #MapKeys(%DeployConfigs)
{
...
}
So far I'm getting nowhere fast with execution errors saying "Invalid value for property Map; expected map."
Further doing something like set %executionvar = %DeployConfigs complains that a map cannot be set to a scaler value.
The variable, DeployConfigs looks like ...
%{"Web.config": ["Web.Beta.config", "Web.Release.config"]}
and is defined at Global scope.
What am I doing wrong?
I'm using buildmaster 5.7.3
Maps are specified as %(key: value), here is an example plan that should help:
set %map = %(Web.config: #("Web.Beta.config", "Web.Release.config"));
foreach $key in #MapKeys(%map)
{
set #values = %map[$key];
Log-Information `$key = $key;
Log-Information `#values = $Join(", ", #values);
}
Sleep 3;

$.grep on JSON data in multiple array.fields using wildcards?

First off I have looked through similar looking questions but have not found the exact problem asked or answered, so here goes :
I have a JSON Object which consists of about 900+ posts. Looking like this:
var JsonData = [{"rowNumber":563663,"hasWarning":true,"isInvoiceAccount":true,"phone":"","name":"Romerike AS","address1":"Co/Skanning","address2":"PB 52","attention":"","mobile":"","email":"fakt#bos.no","fax":"","zipCity":"N-1471 Askim","invoiceAccount":"","notes":null,"account":"3","country":"NORGE","salesRep":"4","countryCode":"no"},{"rowNumber":563674,"hasWarning":false,"isInvoiceAccount":true,"phone":"","name":"LILLEHAMMER","address1":"POSTBOKS 110","address2":"","attention":"","mobile":"","email":"","fax":"","zipCity":"N-2605 LILLEHAMMER","invoiceAccount":"","notes":null,"account":"14","country":"NORGE","salesRep":"4","countryCode":"no"},{"rowNumber":563676,"hasWarning":true,"isInvoiceAccount":true,"phone":"63929788","name":"Askim Bil AS","address1":"Postboks 82","address2":"","attention":"","mobile":"","email":"karosseri#nyg.no","fax":"","zipCity":"N-2051 Askim","invoiceAccount":"","notes":null,"account":"16","country":"NORGE","salesRep":"4","countryCode":"no"},{"rowNumber":563686,"hasWarning":false,"isInvoiceAccount":true,"phone":"69826060","name":"KAROSSERI A/S","address1":"POSTBOKS 165","address2":"","attention":"","mobile":"","email":"tkar#online.no","fax":"","zipCity":"N-1860 TRØGSTAD","invoiceAccount":"","notes":null,"account":"26","country":"NORGE","salesRep":"4","countryCode":"no"},{"rowNumber":563690,"hasWarning":false,"isInvoiceAccount":true,"phone":"","name":"AUTOSERVICE A/S","address1":"POSTBOKS 15","address2":"","attention":"","mobile":"","email":"","fax":"","zipCity":"N-2851 LENA","invoiceAccount":"","notes":null,"account":"30","country":"NORGE","salesRep":"4","countryCode":"no"},{"rowNumber":563691,"hasWarning":false,"isInvoiceAccount":false,"phone":"","name":"ØYHUS A/S","address1":"POSTBOKS 321","address2":"","attention":"John Doe","mobile":"","email":"","fax":"","zipCity":"N-2817 GJØVIK","invoiceAccount":"","notes":null,"account":"31","country":"NORGE","salesRep":"4","countryCode":"no"}];
I want to filter these data before I read them into a table using $.grep.
The JSON data have been loaded as an object.
In the HTML page I have a textfield named "filter".
The following code works, but only when I search for an exact match:
var JsonFiltered = $.grep(JsonData, function (element, index) {
return element.zipCity == $('#filter').val();
});
$.each( JsonFiltered, function ( index, value ) {
// sorting through the array adding values to a table
[...]
});
Problem 1:
I want to use Wildcards when filtering.
I read something about using regexp but I haven't found any viable examples.
Problem 2:
I want to be able to filter more than one column.
Example: filtering the word "Askim" in both element.name and element.zipCity
So I figured out the solutions myself...
Using Wildcards:
var search_term = $('#filter').val();
var search = new RegExp(search_term, "i");
var JsonFiltered = $.grep(JsonTest, function (element, index) {
var zipC = search.test(element.zipCity)
var names = search.test(element.name)
return zipC + names ;
The solution was to use "new RegExp" with the filter "i" setting.
then I took two search.tests combined them in the return command and... presto
Hope this helps anyone else.

Partially update a session variable in meteor?

I think that I might be missing something. I've got the entire contents of a user's product order form stored in a session variable.
var orderFormContents = {
numDoors: 4
numWheels: 4
numSeats: 5
};
Session.set("orderFormContentsSessionVar", orderFormContents);
How do I update the value of just one key in orderFormContentsSessionVar, for instance, just numDoors?
I don't want to overwrite the entire existing contents of the session var.
I would love to be able to do something like:
Session.set("orderFormContentsSessionVar.numDoors", 2);
Something equivalent to _.extend
UPDATE
Following the example of the answer below, I just wrote a function for it:
var updateSession = function(sessionVarName, updateParams){
var obj = Session.get(sessionVarName);
_.extend(obj, updateParams);
Session.set(sessionVarName, obj);
console.log("updated session name: ", sessionVarName, "new session contents: ", Session.get(sessionVarName));
};
Using like you proposed:
var obj = Session.get("orderFormContentSessionVar");
Session.set("orderFormContentsSessionVar", _.extend(obj, {numDoors: 2}));
_.extend should work just fine.
Session.set( "orderFormContentsSessionVar",
_.extend(Session.get("orderFormContentsSessionVar"), { numSeats: 10 }) )
I doubt there is any other way.

Flex 3: Using array item value as an objects name

If I have a list of items in an array that represent the names of modules:
var phaseNames:Array = new Array("directorsPrep", "checkIO", "pickupPhoto", "pickupPhoto", "syncing", "dailies", "pictureEdit", "soundEdit", "soundMix", "colorCorrection", "finishing");
and I want to go through each one of these and call a function within each instance of each module, how would I go about doing so. So far, I have the following:
private function changeStartViewDate(numDays:Number):void
{
startViewDate = rightDate(startViewDate.getMonth(), startViewDate.getDate() + numDays, startViewDate.getFullYear());
getDateInfo();
determineCalendarWeek();
var phaseNames:Array = new Array("directorsPrep", "checkIO", "pickupPhoto", "pickupPhoto", "syncing", "dailies", "pictureEdit", "soundEdit", "soundMix", "colorCorrection", "finishing");
for (var i:int = 0; i < wholeProject.length; i++)
{
wholeProject[i].moveProject(Number((1-2) * numDays));
}
for (i = 0; i < phaseNames.length; i++)
{
for (var j:int = 0; j < [phaseNames[i]].length; j++)
{
[phaseNames[i]].movePhase(Number((-1) * numDays));
}
}
}
But when I try to save it, I get the following error:
1084: Syntax Error: expecting identifier before dot.
It's telling me the error is on the following line:
[phaseNames[i]].movePhase(Number((-1) * numDays));
I tried doing something like the following, but it didn't work:
[phaseNames[i].movePhase(Number((-1) * numDays))];
The above attempt of trying to figure this out gave me the following error
1064: Invalid metadata.
Any help would be appreciated.
I am going to assume that:
Each value of your phaseNames array references an actual instance of some other class [and not the name of the class]
The instance defined in the phaseNames array is a child of the current class.
You should be able to do something like this:
var childName = phaseNames[0];
var myChild : myObjectType = this[childName];
// then call function
myChild.doStuff();
This approach is not dissimilar to what you have; I'm just doing it in more lines. I'm also adding the this keyword to access the child.
I bet if you tried this, directly, it would work:
this[phaseNames[i]].movePhase(Number((-1) * numDays));
I have to wonder why you haven't created an array of all the instances instead of an array of all the variables names that point to the instances.

firefox extension SQLite saving and getting

Ok now for the juicy stuff. All attempts failed to save my string so far.
Here is the code for saving it in sqllite in firefox extension:
var file = Components.classes["#mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("my_db_file_name.sqlite");
var storageService = Components.classes["#mozilla.org/storage/service;1"]
.getService(Components.interfaces.mozIStorageService);
var mDBConn = storageService.openDatabase(file);
mDBConn.execute("CREATE TABLE IF NOT EXISTS log_det (id INTEGER PRIMARY KEY AUTOINCREMENT, acc STRING)");
mDBConn.execute("INSERT INTO log_det (acc) VALUES(" + window['gluistr']+ ")");
mDBConn.drop();
And the code for retrieving the value:
var file = Components.classes["#mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
file.append("my_db_file_name.sqlite");
var storageService = Components.classes["#mozilla.org/storage/service;1"]
.getService(Components.interfaces.mozIStorageService);
var mDBConn = storageService.openDatabase(file);
var res = mDBConn.execute("SELECT * FROM log_det");
mDBConn.drop();
Is not working. Anybody knows why? Is "execute" ok or do I need "createStatement" or "executeSimpleSQL". I am confused.
Use executeSimpleSQL.
openDatabase returns a mozIStorageConnection instance, which does not have any method named execute. You can use executeSimpleSQL any time you want to execute a SQL statement without bound parameters (which is what you're doing).
You were probably thinking of mozIStorageStatement's execute method. executeSimpleSQL is not sufficient when bound parameters are necessary. Instead, you need to create a statement, bind any parameters, and then execute it:
var statement = mDBConn.createStatement(
"SELECT * FROM log_det WHERE column_name = :parameter");
statement.bindStringParameter(0, "value");
statement.execute();
statement.reset();
Also note that mozIStorageConnection does not have any method named drop. Maybe you meant to write mDBConn.close()?
All of this is covered here:
https://developer.mozilla.org/en/storage

Resources