Using JS objects for your own needs

General Add comments
by:

One of the benefits of an object oriented language, is the ability to instantiate classes and manipulating the instance of that class.
Current is an instance of a GlideRecord.
The constructor or class of an object is always the ‘template’ for an instance of that specific object.
Even new Object has the constructor Object.

In javascript, var x = new Object or var x = {}, will create an instance of Object in variable x.

This is not surprising for a OOP-language.

One of the biggest benefits of this however is the flexibility it provides.
Now we know that current is an instance of a GlideRecord, we know it can be manipulated as any instance can.
Imagine we’d be creating a before business rule and want to use (or abuse??) the current object that is available.

Try the following two business rules:

Name: Before BR
When: Before
On: Insert, Update
Script: current.nvar_test_value = ‘Hello! I am being transferred from the before to the after current object.’;

Name: After BR
When: After
On: Insert, Update
Script: gs.print(current.nvar_test_value);

Put them on a random table and either create or update a record.
Also note that prints will only appear when you have your debugger on, so make sure its running.

As you can see, the ‘nvar_test_value’ which normally does not exist in a current object, was transferred to an after business rule.
This means you can transfer variables where necessary, to other business rules.
This holds true for every object that is available in the context.

Some nice examples to use:

  • gs
  • g_form
  • g_list
  • current


And you might come up with some other objects yourself.
Incidentally, we’ve also shown that the current is the same during the transaction.
Makes sense as it would be redundant to create a new version of the object for every single business rule.

The feature however is not completely without danger.
It is possible the adjustment to the instantiated object might actually overwrite an existing property of the instance.
Imagine the following case for the previous business rules, by adjusting the scripts we created above:

Before BR:
//to indicate a record has changed, we want to store changes in a variable to know in the after script whether the record changed
//even though we know no BR triggers when no update was done to the record.
current.changes = true;

After BR:
gs.print(‘This record has changed is ‘ + current.changes);

“Ah perfect!” you might say. “I can see that my record changed from an after business rule!”.
And yes you are absolutely right.
But what complication did you just create?
Create another business rule:

Name: After BR 2
When: After
On: Insert, Update
Script: if(current.changes()){gs.print(‘I changed’);} else {gs.print(‘I did not change’);}

“Hmmm why didn’t it create a printed message?”
What you’ve just done is accidentily overwritten a property/attribute of your instance of current, that contained a function.
You can check your log for the following message:

org.mozilla.javascript.EcmaError: true is not a function.
Caused by error in Business Rule: ‘After BR 2’ at line 1

==> 1: if(current.changes()){gs.print(‘I changed’);} else {gs.print(‘I did not change’);}

It tries to execute true.
This is the same true we put in the instantiated object in the before business rule.
We can’t execute true, because that is meaningless.
So be aware when using this feature, as you might accidentally overwrite some features of one of the said objects.

If you have any question on this you can contact me via email on wesley.bouwer2e2.nl

2 Responses to “Using JS objects for your own needs”

  1. Robert Ninness Says:

    Hi Wesley,

    Cool post I didn’t know that the current object used in the before and after rules was the same instance, but it makes sense that it is!

    Another way of passing variables between business rules is declaring global variables, rules that are a higher order will be able to make use of them. They don’t get carried over from before to after rules though.

    Nice tip, I will keep it in my bag of tricks 😀

    Have you tried this with the Javascript prototype? I wonder if adding properties via prototype will make them accessible where ever GlideRecord can be called?

    ~Robert

  2. Wesley Bouwer Says:

    Hi Robert,

    Yup, you are right. It is also quite dangerous, as the context exists across the entire transaction, not just the entire set of business rules on one table. If you update a record via business rules on one table, it can trigger the business rules for the record that was updated as well. The variable would still be declared in this context.

    And yes I have used prototype. It can be used to extend classes the same way as described above. As global business rules are regarding cross-transaction context, they would be ideal to use in this scenario.

    As proof of concept, try creating 2 business rules:

    BR 1
    Table: Global
    Script:

    GlideRecord.prototype.plsTestMyFunctionAddition = function(arg) {
    gs.print(‘Testing : ‘ + arg);
    };

    BR 2
    Table Incident
    Script:

    current.plsTestMyFunctionAddition(‘Hi there, I work from here as well!’);

    Turn on the debugger and make sure the script runs on the transaction. Be cautious when using it though 🙂

    Regards,

    Wesley

Leave a Reply