Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

John Caruso
Kilo Guru
 
After many months seeking enlightment and inspiration for continuing this series of articles, we're finally ready to continue our functional journey!

(Or, I'm just a lazy guy who procastinated for far too long... ;-))

In Part 1, we created a simple query helper function that separated GlideRecord query and looping logic from record-level processing logic.

For this article, we'll review some record-level processing logic and as we did before, look for opportunities to factor out repeated, boilerplate code.

Here's some real world code (adapted from HAAPIs script include):
function ex_1() {
    var gr = new GlideRecord('sys_cluster_state');
    gr.get('status', 'online');

    var lastDate = gr.most_recent_message.getGlideObject().getRaw();
    var lastDateSecs = (new Packages.java.util.Date().getTime() - lastDate.getTime()) / 1000;
    var nodeConfig = {
        sys_id: gr.sys_id.toString(),
        system_id: gr.system_id.toString(),
        status: gr.status.toString(),
        last_checkin: gr.most_recent_message.toString(),
        last_checkin_friendly: GlideDateUtil.getDateTimeString(lastDateSecs, true)
    };

    return nodeConfig;
}
 
We'll cleanup some of the old Legacy API code too, but did you notice some repeated code related to GlideRecord? Yes, the `.toString()` calls on each of the fields being mapped to the nodeConfig object.

Alternatively, you may see the `gr.system_id + ''` technique, or perhaps `gr.getValue('system_id')`.

If you're not aware, these are all methods to get a string representation of the underlying value encapsulated by the GlideElement object - which is what is returned when you access a GlideRecord property (field).

We often need a string value (or non-reference type) to ensure we get a "copy" of the GlideElement value, rather than a reference to the GlideElement itself - which remains constant while looping over a set of GlideRecords, and often results in unexpected behavior.

Wouldn't it be nice if GlideRecord just returned values instead of GlideElement references? Well, that's a topic for another day, but for now, let create a little helper function to do just that.
function mapGR(gr) {
    function mapField(obj, field) {
        obj[field] = gr[field].toString();
        return obj;
    }
    var fields = Object.keys(gr).sort();
    return fields.reduce(mapField, {});
}
 
Let's clean up and refactor our first example to use the mapGR function:
function ex_2() {
    var gr = new GlideRecord('sys_cluster_state');
    gr.get('status', 'online');
    var node = mapGR(gr);

    var lastDate = new GlideDateTime(gr.most_recent_message).getNumericValue();
    var lastDateSecs = Math.floor((Date.now() - lastDate) / 1000) + ' seconds';
    var nodeConfig = {
        sys_id: node.sys_id,
        system_id: node.system_id,
        status: node.status,
        last_checkin: node.most_recent_message,
        last_checkin_friendly: lastDateSecs
    };

    return nodeConfig;
}
 
Looks a bit cleaner without the `.toString()` cruft in our code, eh?

Next time, we'll enhance the mapGR function to do even more declarative and functional stuff.
Version history
Last update:
‎10-06-2019 10:48 AM
Updated by: