The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
SlightlyLoony
Tera Contributor

find_real_file.pngWhen you're using GlideRecords in JavaScript, getting properties on the GlideRecord instance may not do exactly what you think they do — and this difference can get you in trouble! For example, consider this little snippet of code:


var map = {};
var gr = new GlideRecord('cmdb_ci_server');
gr.query();
while (gr.next()) {
map[gr.name] = gr.ip_address;
}
for(var name in map) {
gs.log(name + ': ' + map[name]);
}


You might reasonably expect this to create a map of server names to their respective IP addresses — but you would be surprised. If you actually run this code, you'll see all the server names, but they'll all have the same IP address.

What's going on here?

The unexpected results are caused by a subtlety in what "gr.ip_address" actually returns. You might expect that it would return the value of the IP address field, but it does not. Instead, it returns the instance of GlideElement that represents the IP address field — and (here's the key) there are only one of these instances, no matter how many rows there are in the query result. So the map gets built with the same object being assigned to every property. When the code above prints the value of all the properties in the map, it gets the same object back for each property, always with the value of the last row in the query result.

You might ask why the "gr.name" appears to work for setting the property names in the map, when the IP address failed so miserably. The answer is that JavaScript expects a string for setting the property name, so it calls the "toString()" method on the GlideElement instance — and that returns the value contained in the name GlideElement at that moment, and so it works. In the case of the IP address GlideElement, there's no requirement to be a string (a property may be assigned any kind of object, after all), so this forced conversion never takes place.

Fortunately the cure is very simple:


var map = {};
var gr = new GlideRecord('cmdb_ci_server');
gr.query();
while (gr.next()) {
map[gr.name] = gr.getValue('ip_address');
}
for(var name in map) {
gs.log(name + ': ' + map[name]);
}


All we've done is to replace the "gr.ip_address" with "gr.getValue('ip_address')". The gr.getValue() method always returns a string representing the value in the GlideElement at that moment, so we are safe. In fact there are numerous ways to make this code work:


// just replace gr.ip_address with any of these:
gr.getValue('ip_address')
new String(gr.ip_address)
'' + gr.ip_address
gr.ip_address.toString()


We prefer the obviousness of the "getValue()" syntax, but in fact all these methods work equally well.