SlightlyLoony
Tera Contributor

find_real_file.pngWhat do you think is logged when you run the following script, assuming that you have three computers named "Aleck", "Ben", and "Tom" in your CMDB?


var gr = new GlideRecord('cmdb_ci_computer');
gr.orderBy('name');
gr.query();
var name;
var sys_id;
while (gr.next()) {
if (gr.name == 'Ben') {
name = gr.name;
sys_id = gr.sys_id;
}
}
gs.log(name + ' @ ' + sys_id);

If you thought it would log Ben and its sys_id, why, then, you would be wrong. Here's why:

This code will always log the name and sys_id of the last computer it iterates over — in this case, "Tom". The reason for this is ever-so-slightly subtle, so follow along carefully...

First, the code inside the "if" block probably isn't doing what you think it's doing. In particular, it's not assigning the string value of the name field to the name variable, nor is it assigning the string value of the sys_id field to the sys_id variable. Instead, it's assigning the GlideElement instance for each field to its respective variable. If you're not familiar with GlideElement, you can read all about it here.

Now here's the slightly subtle part: any given GlideRecord only has one instance of GlideElement for each field. It does not have a separate instance of GlideElement for each field in each record. Instead, the value within the GlideElement changes each time GlideRecord iterates to a new record. That means that when the while loop finishes, the name variable contains the GlideElement instance for the name field, and the GlideElement instance contains the name value for the last record we iterated over: "Tom".

But if gr.name returns a GlideElement and not a string, then how could the "if" statement work? It's comparing a string to the GlideElement representing the name field! Well, that works because JavaScript coerces the GlideElement to a string (by calling the GlideElement's .toString() method). The variable assignment doesn't need to coerce, because the variable can hold a GlideElement just fine.

To make the code work the way you most likely expected, here's what you can do:

var gr = new GlideRecord('cmdb_ci_computer');
gr.orderBy('name');
gr.query();
var name;
var sys_id;
while (gr.next()) {
if (gr.name == 'Ben') {
name = '' + gr.name;
sys_id = '' + gr.sys_id;
}
}
gs.log(name + ' @ ' + sys_id);

By concatenating the GlideElement references to an empty string, we're forcing JavaScript to coerce the GlideElement to a string. Just as it did in the "if" statement, this retrieves the string value from the GlideElement instead of returning the GlideElement itself...

3 Comments