Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rverrips/753736a57911b1cd8d4574ad3443567e to your computer and use it in GitHub Desktop.
Save rverrips/753736a57911b1cd8d4574ad3443567e to your computer and use it in GitHub Desktop.
ServiceNow EfficientGlideRecord: A MUCH more efficient and performant client-side GlideRecord queries, as efficient as GlideAjax (or more!)
//Client-side
doThing();
function doThing() {
let eGR = new EfficientGlideRecord('incident')
.setLimit(10)
.addNotNullQuery('assignment_group')
.addField('number')
.addField('short_description')
.addField('assignment_group', true) //Get display value as well
.orderBy('number')
.query(function (eGR) {
while (eGR.next()) {
console.log(
'Short description value: ' + eGR.getValue('short_description') + '\n' +
'Number: ' + eGR.getValue('number') + '\n' +
'Assignment group: ' + eGR.getValue('assignment_group') + ' (' +
eGR.getDisplayValue('assignment_group') + ')'
);
}
});
}
var ClientGlideRecordAJAX = Class.create();
ClientGlideRecordAJAX.prototype = Object.extendsObject(AbstractAjaxProcessor, {
gr_config : {},
getPseudoGlideRecord : function() {
var grQuery;
var responseObj = {
'_records' : [],
'_row_count' : 0,
'_config' : {},
'_executing_as' : {
'user_name' : gs.getUserName(),
'user_id' : gs.getUserID()
}
};
this.gr_config = {};
this.gr_config.table_to_query = this.getParameter('table_to_query');
//@type {{get_display_value: boolean, name: string}}
this.gr_config.fields_to_get = this.getParameter('fields_to_get');
this.gr_config.record_limit = this.getParameter('record_limit');
this.gr_config.order_by_field = this.getParameter('order_by_field');
this.gr_config.order_by_desc_field = this.getParameter('order_by_desc_field');
this.gr_config.encoded_queries = this.getParameter('encoded_queries');
this.gr_config.queries = this.getParameter('queries');
//Parse queries/encoded queries array and fields_to_get object
if (this.gr_config.hasOwnProperty('queries') && this.gr_config.queries) {
this.gr_config.queries = JSON.parse(this.gr_config.queries);
}
if (this.gr_config.hasOwnProperty('fields_to_get') && this.gr_config.fields_to_get) {
this.gr_config.fields_to_get = JSON.parse(this.gr_config.fields_to_get);
}
if (this.gr_config.hasOwnProperty('encoded_queries') && this.gr_config.encoded_queries) {
this.gr_config.encoded_queries = JSON.parse(this.gr_config.encoded_queries);
}
gs.info('EfficientGlideRecord config: \n' + JSON.stringify(this.gr_config, null, 2));
if (!this._validateMandatoryConfig()) {
throw new Error(
'Mandatory value not specified. ' +
'Cannot perform query. Halting.\n' +
'Config: \n' +
JSON.stringify(this.gr_config)
);
}
grQuery = this._constructAndGetGlideRecord();
grQuery.query();
while (grQuery.next()) {
responseObj._records.push(
this._getRequestedRecordData(grQuery, this.gr_config)
);
}
responseObj._row_count = responseObj._records.length;
responseObj._config = this.gr_config;
return JSON.stringify(responseObj);
},
_constructAndGetGlideRecord : function() {
var i, queryField, queryOperator, queryValue;
var grQuery = new GlideRecordSecure(this.gr_config.table_to_query);
//Add limit, if specified
if (
this.gr_config.hasOwnProperty('record_limit') &&
this.gr_config.record_limit >= 1
) {
grQuery.setLimit(this.gr_config.record_limit);
}
//add order_by or order_by_desc field, if specified
if (
this.gr_config.hasOwnProperty('order_by_desc_field') &&
this.gr_config.order_by_desc_field
) {
grQuery.orderByDesc(this.gr_config.order_by_desc_field);
}
if (
this.gr_config.hasOwnProperty('order_by_field') &&
this.gr_config.order_by_field
) {
grQuery.orderBy(this.gr_config.order_by_field);
}
//Add encoded query, if specified
if (
this.gr_config.hasOwnProperty('encoded_queries') &&
this.gr_config.encoded_queries
) {
for (i = 0; i < this.gr_config.encoded_queries.length; i++) {
if (this.gr_config.encoded_queries[i]) {
grQuery.addEncodedQuery(this.gr_config.encoded_queries[i]);
}
}
}
//Add field queries if specified
if (
this.gr_config.hasOwnProperty('queries') &&
this.gr_config.queries.length > 0
) {
for (i = 0; i < this.gr_config.queries.length; i++) {
queryField = this.gr_config.queries[i].field;
queryOperator = this.gr_config.queries[i].operator;
queryValue = this.gr_config.queries[i].value;
grQuery.addQuery(queryField, queryOperator, queryValue);
}
}
return grQuery;
},
_validateMandatoryConfig : function() {
var i, currentQuery;
//Can add more later if necessary
var mandatoryFields = [
'table_to_query',
'fields_to_get'
];
for (i = 0; i < mandatoryFields.length; i++) {
if (
!this.gr_config.hasOwnProperty(mandatoryFields[i]) ||
!this.gr_config[mandatoryFields[i]]
) {
return false;
}
}
//If both order_by and order_by_desc are specified, log a warning and ignore order_by_desc.
// if (
// (
// this.gr_config.hasOwnProperty('order_by_field') &&
// this.gr_config.order_by_field
// ) &&
// (
// this.gr_config.hasOwnProperty('order_by_desc_field') &&
// this.gr_config.order_by_desc_field
// )
// ) {
// gs.warn(
// 'ClientGlideRecordAJAX client-callable Script Include called with ' +
// 'both an "order by" and "orderby descending" field. It is only possible to ' +
// 'specify one field to sort by, either ascending or descending. \n' +
// 'Ignoring the descending field, and ordering by the order_by_field field.'
// );
// this.gr_config.order_by_desc_field = '';
// }
if (
this.gr_config.hasOwnProperty('queries') &&
this.gr_config.queries
) {
for (i = 0; i < this.gr_config.queries.length; i++) {
currentQuery = this.gr_config.queries[i];
if (
(!currentQuery.hasOwnProperty('field') || !currentQuery.field) ||
(!currentQuery.hasOwnProperty('operator') || !currentQuery.operator) ||
(!currentQuery.hasOwnProperty('value') || !currentQuery.value)
) {
gs.error(
'Malformed query provided to ClientGlideRecordAJAX Script Include:\n' +
JSON.stringify(currentQuery)
);
return false;
}
}
}
return true;
},
_getRequestedRecordData : function(grRecord, config) {
var i, canReadField, fieldName, fieldValue, fieldDisplayValue, getDisplay;
var recordData = {
'_config' : config,
'_table_name' : grRecord.getTableName(),
'_field_values' : {}
};
for (i = 0; i < recordData._config.fields_to_get.length; i++) {
fieldName = recordData._config.fields_to_get[i].name;
getDisplay = !!recordData._config.fields_to_get[i].get_display_value;
//Gotta get canReadField in this way and use it to see if we can see the field values,
// cause otherwise GlideRecordSecure freaks alll the way out.
canReadField = (grRecord.isValidField(fieldName) && grRecord[fieldName].canRead());
fieldValue = canReadField ? (grRecord.getValue(fieldName) || '') : '';
fieldDisplayValue = (getDisplay && canReadField && fieldValue) ?
(grRecord[fieldName].getDisplayValue() || '') : ('');
/*gs.debug(
'EfficientGlideRecord\n' +
'Using fields to get: ' + JSON.stringify(recordData._config.fields_to_get) +
'\nGot current field name "' + fieldName + '". \n' +
'Getting display: ' + getDisplay + '\n' +
'Field value: ' + fieldValue
);*/
//Retrieve value (and display value if requested)
recordData._field_values[fieldName] = {
'name' : fieldName,
'value' : fieldValue,
'display_value' : fieldDisplayValue,
//If false, may be caused by ACL restriction, or by invalid field
'can_read' : canReadField
};
}
return recordData;
},
type : 'ClientGlideRecordAJAX'
});
/**
* @classdesc https://snprotips.com/ todo: Article link here
* @class
* @author
* Tim Woodruff (https://TimothyWoodruff.com)
* SN Pro Tips (https://snprotips.com)
* @license
* Copyright (c) 2022 Tim Woodruff (https://TimothyWoodruff.com)
* & SN Pro Tips (https://snprotips.com).
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* Alternative licensing is available upon request. Please contact tim@snc.guru
* for more info.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @version 1.0.0
*/
class EfficientGlideRecord {
/**
* Instantiated with the 'new' keyword (as classes typically are when instantiated), this
* will construct a client-side EfficientGlideRecord object. The methods of this class can
* then be called to construct a client-side GlideRecord query. EfficientGlideRecord
* replicates *most* of the functionality of the client-side GlideRecord object, but
* with more and enhanced functionality.
* EfficientGlideRecord is FAR preferable to using the out-of-box (OOB) client-side
* GlideRecord query (even asynchronously), because GlideRecord returns a massive amount
* of unnecessary data, and can be much, much slower. EfficientGlideRecord aims to return
* only that data which is necessary and requested from the server, thus providing an
* efficient interface to query records asynchronously without all the additional overhead
* related to information that you don't need.
*
* Additional documentation can be found on the SN Pro Tips blog, at https://go.snc.guru/egr
* NOTE: For info on performing async queries in onSubmit Client Scripts, see
* https://go.snc.guru/onsubmit
*
* @param {String} tableName - The name of the table on which to execute your GlideRecord query
* @returns {EfficientGlideRecord}
* @example
* var egrIncident = new EfficientGlideRecord('incident');
* egrIncident.addField('number')
* .addField('assignment_group', true)
* .addField('assigned_to', true);
*
* egrIncident.get('some_incident_sys_id', function(egrInc) {
* g_form.addInfoMessage(
* egrInc.getValue('number') + '\'s assignment group is ' +
* egrInc.getDisplayValue('assignment_group') + ' (sys_id: ' +
* egrInc.getValue('assignment_group') + ')\n' +
* 'The assignee is ' + egrInc.getDisplayValue('assigned_to') + ' (sys_id: ' +
* egrInc.getValue('assigned_to') + ')'
* );
* });
* @constructor
*/
constructor(tableName) {
if (!tableName) {
throw new Error(
'EfficientGlideRecord constructor called without a valid tableName ' +
'argument. Cannot continue.'
);
}
this._config = {
'table_to_query' : tableName,
'fields_to_get' : [],
'record_limit' : 0,
'order_by_field' : '',
'order_by_desc_field' : '',
'encoded_queries' : [],
'queries' : []
};
this._row_count = -1;
this._query_complete = false;
this._records = [];
this._current_record_index = -1;
this._current_record = {};
this._gaQuery = new GlideAjax('ClientGlideRecordAJAX');
this._gaQuery.addParam('sysparm_name', 'getPseudoGlideRecord');
return this; //todo: Necessary on constructor method?
}
/**
* Add a field to retrieve from the target record(s).
* Any fields not specified by calling this method will not be available on the resulting
* EfficientGlideRecord object in the callback function after calling .query(). In this
* case, a warning will be shown in the console, and .getValue('field_name') will return
* a blank string.
* If a second argument (getDisplayValue) is not specified and set to true, then the
* field's display value will not be available on the resulting EfficientGlideRecord
* object in the callback function. In this case, .getDisplayValue('field_name') will
* return a blank string.
* @param {String} fieldName - The name of the field to retrieve from the server for the
* specified record(s).
* @param {Boolean} [getDisplayValue=false] - Set this argument to true in order to
* retrieve the display value for the specified field. If this is not set to true then
* calling .getDisplayValue('field_name') will cause a warning to be logged to the
* console, and a blank string will be returned.
* @returns {EfficientGlideRecord}
* @example
* var egrIncident = new EfficientGlideRecord('incident');
* egrIncident.addField('number')
* .addField('assignment_group', true)
* .addField('assigned_to', true);
*
* egrIncident.get('some_incident_sys_id', function(egrInc) {
* g_form.addInfoMessage(
* egrInc.getValue('number') + '\'s assignment group is ' +
* egrInc.getDisplayValue('assignment_group') + ' (sys_id: ' +
* egrInc.getValue('assignment_group') + ')\n' +
* 'The assignee is ' + egrInc.getDisplayValue('assigned_to') + ' (sys_id: ' +
* egrInc.getValue('assigned_to') + ')'
* );
* });
*/
addField(fieldName, getDisplayValue) {
this._config.fields_to_get.push({
'name' : fieldName,
'get_display_value' : (!!getDisplayValue)
});
return this;
}
/**
* Add a query to the EfficientGlideRecord object.
* By specifying a field name, operator, and value, you can perform all sorts of queries.
* If only two arguments are specified, then it's assumed that the first is the field
* name and the second is the field value. The operator will automatically be set to "=".
*
* @param {String} fieldName - The name of the field to perform the query against.
* @param {String} [operator="="] - The operator to use for the query.
* Valid operators:
* Numbers: =, !=, >, >=, <, <=
* Strings: =, !=, STARTSWITH, ENDSWITH, CONTAINS, DOES NOT CONTAIN, IN, NOT IN, INSTANCEOF
* Note: If only two arguments are specified (fieldValue is not defined), then the second
* argument will be treated as the value, and the operator will automatically be set to "=".
* @param {String} fieldValue - The value to compare, using the specified operator, against
* the specified field.
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling (as seen in the example below).
* @example
* new EfficientGlideRecord('incident')
* .setLimit(10)
* .addQuery('assignment_group', '!=', 'some_group_sys_id')
* .addQuery('assigned_to', 'some_assignee_sys_id')
* .addNotNullQuery('assignment_group')
* .addField('number')
* .addField('short_description')
* .addField('assignment_group', true) //Get display value as well
* .orderBy('number')
* .query(function (egrIncident) {
* while (egrIncident.next()) {
* console.log(
* 'Short description value: ' + egrIncident.getValue('short_description') + '\n' +
* 'Number: ' + egrIncident.getValue('number') + '\n' +
* 'Assignment group: ' + egrIncident.getValue('assignment_group') + ' (' +
* egrIncident.getDisplayValue('assignment_group') + ')'
* );
* }
* });
*/
addQuery(fieldName, operator, fieldValue) {
if (typeof fieldValue === 'undefined') {
fieldValue = operator;
operator = '=';
}
this._config.queries.push({
'field' : fieldName,
'operator' : operator,
'value' : fieldValue
});
return this;
}
/**
* Shorthand for this.addQuery(fieldName, '!=', 'NULL');.
* @param {String} fieldName - The name of the field to ensure is not empty on returned
* records.
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
* @example
* new EfficientGlideRecord('incident')
* .setLimit(10)
* .addQuery('assignment_group', '!=', 'some_group_sys_id')
* .addQuery('assigned_to', 'some_assignee_sys_id')
* .addNotNullQuery('assignment_group')
* .addField('number')
* .addField('short_description')
* .addField('assignment_group', true) //Get display value as well
* .orderBy('number')
* .query(function (egrIncident) {
* while (egrIncident.next()) {
* console.log(
* 'Short description value: ' + egrIncident.getValue('short_description') + '\n' +
* 'Number: ' + egrIncident.getValue('number') + '\n' +
* 'Assignment group: ' + egrIncident.getValue('assignment_group') + ' (' +
* egrIncident.getDisplayValue('assignment_group') + ')'
* );
* }
* });
*/
addNotNullQuery(fieldName) {
this.addQuery(fieldName, '!=', 'NULL');
return this;
}
/**
* Shorthand for .addQuery(fieldName, '=', 'NULL')
* @param {String} fieldName - The name of the field to use in your query, getting only
* records where this field is empty.
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
addNullQuery(fieldName) {
this.addQuery(fieldName, '=', 'NULL');
return this;
}
/**
* Add an encoded query string to your query. Records matching this encoded query will
* be available in your callback function after calling .query().
* @param {String} encodedQueryString - The encoded query string to use in your query.
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
addEncodedQuery(encodedQueryString) {
if (!encodedQueryString || typeof encodedQueryString !== 'string') {
throw new Error(
'Invalid encoded query string specified. Encoded query must be a valid ' +
'non-empty string.'
);
}
this._config.encoded_queries.push(encodedQueryString);
return this;
}
/**
* Very similar to .addEncodedQuery(), except that it REPLACES any existing encoded
* queries on the GlideRecord, rather than adding to them.
* @param {String} encodedQueryString - The exact encoded query, as a string, to use in
* your query.
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
setEncodedQuery(encodedQueryString) {
//REPLACE existing encoded queries, rather than add to them like .addEncodedQuery().
this._config.encoded_queries = [encodedQueryString];
return this;
}
/**
* todo: docs
* @param orderByField
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
addOrderBy(orderByField) {
this.orderBy(orderByField);
return this;
}
/**
* todo: docs
* @param orderByField
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
orderBy(orderByField) {
this._config.order_by_field = orderByField;
return this;
}
/**
* todo: docs
* @param orderByDescField
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
orderByDesc(orderByDescField) {
this._config.order_by_desc_field = orderByDescField;
return this;
}
/**
* todo: docs
* @param limit
* @returns {EfficientGlideRecord} - Returns the instantiated object for optional
* chain-calling.
*/
setLimit(limit) {
if (typeof limit !== 'number' || limit <= 0) {
throw new Error(
'EfficientGlideRecord.setLimit() method called with an invalid argument. ' +
'Limit must be a number greater than zero.'
);
}
this._config.record_limit = limit;
return this;
}
/**
* todo: docs
* @param sysID
* @param callbackFn
*/
get(sysID, callbackFn) {
this.addQuery('sys_id', sysID);
this.setLimit(1);
this.query(callbackFn);
}
/**
* Perform the async query constructed by calling methods in this class, and get the
* field(s) from the resultant record that were requested by calling
* .addField(fieldName, getDisplayValue)
* @async
* @param {EfficientGlideRecord~query} callbackFn - The callback function that will
* be executed when the request is complete.
* This callback function will be called with one argument. That argument will be the
* instantiated EfficientGlideRecord object containing the details about the records
* returned from your query, and the methods in this class for interacting with them as
* documented in this class.
*/
query(callbackFn) {
let paramName;
if (!this._readyToSend()) {
//Meaningful errors are logged by this._readyToSend().
return false;
}
for (paramName in this._config) {
//Prevent iteration into non-own properties
if (!this._config.hasOwnProperty(paramName)) {
continue;
}
let paramVal;
if (typeof this._config[paramName] === 'object') {
paramVal = JSON.stringify(this._config[paramName]);
} else {
paramVal = this._config[paramName];
}
this._gaQuery.addParam(
paramName,
paramVal
);
}
this._gaQuery.getXMLAnswer(function (answer, eGR) {
answer = JSON.parse(answer);
//let answer = response.responseXML.documentElement.getAttribute('answer');
// answer = JSON.parse(answer); //Throws if unparseable -- good.
if (!answer.hasOwnProperty('_records')) {
throw new Error(
'Something went wrong when attempting to get records from the server.\n' +
'Response object: \n' +
JSON.stringify(answer)
);
}
eGR._query_complete = true;
eGR._records = answer._records;
eGR._row_count = answer._row_count;
eGR._executing_as = answer._executing_as;
callbackFn(eGR);
}, null, this);
}
/* The following methods can only be called after the query is performed */
/**
*
* Can only be called from the callback function passed into .query() after the query
* has completed.
* @returns {boolean}
*/
hasNext() {
if (!this._query_complete) {
/*throw new Error(
'The .hasNext() method of EfficientGlideRecord can only be called from the ' +
'callback function after calling .query()'
);*/
return false;
}
return (this._row_count > (this._current_record_index + 1));
}
/**
* todo: docs
* @returns {boolean}
*/
next() {
if (!this._query_complete) {
/*throw new Error(
'The .next() method of EfficientGlideRecord can only be called from the ' +
'callback function after calling .query()'
);*/
return false;
}
if (!this.hasNext()) {
return false;
}
this._current_record_index++;
this._current_record = this._records[this._current_record_index];
return true;
}
/**
* Returns true if the specified field exists and can be read (even if it's blank).
* Will return false in the following cases:
* -The specified field on the current record cannot be read
* -The specified field does not exist in the response object (which may happen if you don't
* add the field to your request using .addField()).
* -The specified field does not exist in the database
* @param {String} fieldName - The name of the field to check whether the user can read or not.
* @returns {Boolean} - Returns true if the specified field exists and can be read, or
* false otherwise.
*/
canRead(fieldName) {
if (!this._query_complete) {
throw new Error(
'The .canRead() method of EfficientGlideRecord can only be called from the ' +
'callback function after calling .query(callbackFn)'
);
}
if (!this._current_record._field_values.hasOwnProperty(fieldName)) {
console.warn(
'There is no field with the name ' + fieldName + ' in the ' +
'EfficientGlideRecord object. Did you remember to specify that you want to ' +
'get that field in the query using .addField()?'
);
return false;
}
if (!this._current_record._field_values[fieldName].hasOwnProperty('can_read')) {
console.warn(
'The requested field "' + fieldName + '" has no can_read node. ' +
'This should not happen. Returning a blank false.'
)
return false;
}
return this._current_record._field_values[fieldName].can_read || false;
}
/**
* todo: docs
* @param fieldName
* @returns {string}
*/
getValue(fieldName) {
if (!this._query_complete) {
throw new Error(
'The .getValue() method of EfficientGlideRecord can only be called from the ' +
'callback function after calling .query(callbackFn)'
);
}
if (!this._current_record._field_values.hasOwnProperty(fieldName)) {
console.warn(
'There is no field with the name ' + fieldName + ' in the ' +
'EfficientGlideRecord object. Did you remember to specify that you want to ' +
'get that field in the query using .addField()?'
);
return '';
}
if (!this._current_record._field_values[fieldName].hasOwnProperty('value')) {
console.warn(
'The requested field "' + fieldName + '" has no value node. ' +
'This should not happen. Returning a blank string.'
)
return '';
}
return this._current_record._field_values[fieldName].value || '';
}
/**
* todo: docs
* @param fieldName
* @returns {string|*|string}
*/
getDisplayValue(fieldName) {
if (!this._query_complete) {
throw new Error(
'The .getDisplayValue() method of EfficientGlideRecord can only be called from the ' +
'callback function after calling .query(callbackFn)'
);
}
if (!this._current_record._field_values.hasOwnProperty(fieldName)) {
console.warn(
'There is no field with the name ' + fieldName + ' in the ' +
'EfficientGlideRecord object. Did you remember to specify that you want to ' +
'get that field in the query using .addField()?'
);
return '';
}
if (
!this._current_record._field_values[fieldName].hasOwnProperty('display_value') ||
!this._current_record._field_values[fieldName].display_value
) {
console.warn(
'There is no display value for the field with the name ' + fieldName +
' in the EfficientGlideRecord object. Did you remember to specify that you ' +
'want to get that field\'s display value in the query using ' +
'.addField(fieldName, true)?'
);
return '';
}
return this._current_record._field_values[fieldName].display_value || '';
}
/* Private helper methods below */
_readyToSend() {
/* todo:
-Validate table name is specified
-Validate this._config.fields_to_get is set and contains at least one value
*/
if (!this._config.table_to_query) {
console.error(
'EfficientGlideRecord not ready to query. Table name was not specified in ' +
'the constructor\'s initialize argument.'
);
return false;
}
if (
!this._config.fields_to_get ||
this._config.fields_to_get.length < 1
) {
console.error(
'EfficientGlideRecord not ready to query. No fields were specified to ' +
'retrieve. \nPlease specify which fields you want to retrieve from the ' +
'GlideRecord object using .addField(fieldName, getDisplayValue). ' +
'Afterward, in your callback, you can use .getValue(fieldName). If ' +
'you set getDisplayValue to true, you can also use ' +
'.getDisplayValue(fieldName).'
);
return false;
}
//Warn if queries AND encoded queries are both empty and limit is unspecified
// (but don't return false)
if (
(
!this._config.hasOwnProperty('queries') ||
this._config.queries.length < 1
) &&
(
!this._config.hasOwnProperty('encoded_queries') ||
this._config.encoded_queries.length < 1
) &&
(
!this._config.hasOwnProperty('record_limit') ||
this._config.record_limit < 1
)
) {
console.warn(
'The EfficientGlideRecord query has no query and no record limit ' +
'associated with it. This may result in poor performance when querying larger ' +
'tables. Please make sure that you need all records in the specified table, ' +
'as all records will be returned by this query.'
);
}
//Return true if none of the above validations have failed.
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment