Expressions, values, and operators of Automation Rules
This section describes the use of expressions in automation rules: what expressions, values (variables), and operators exist, and how they are used in the system when creating a rule. There are many values and operators available for use in rules. The expressions are grouped by type and are listed below along with usage examples.
Terminology
In the context of automation rules, the following terms are used, which have different interpretations:
Expression is a construction containing the value(s) and operator(s).
Value (variable) - a specific quantity (numbers, text, logical quantities, dates, etc.).
The operator is an action. The operator sets a command or connects conditions to each other: what exactly needs to be done with the values.
Example: some_expression: a + 3, where some_expression is the name of the expression, a + 3 is the expression itself, a and 3 are values (or variables), + is the operator.
Basic principles
Please note: Expressions calculate values, which are then used in the condition and actions of the automation rule. Each line of the expression block has a name and a formula: name: expression (as in the example above: some_expression: a + 3). The name becomes the value (variable) of the rule and can be further used in conditions, actions, and subsequent expressions.
The expression is written in the format:
Expression name: value
The expression name consists of Latin letters, numbers, and underscores. As a value, you can use:
- a link to a field or related record:
requested_by,requested_by.manager,requests[first]; - the previous value of the field separated by the suffix
_was:status_was,team_was,custom_fields_was.priority; - a string in single or double quotes;
- number:
10,3.5; - static value:
accepted,incident',high`; - value of the custom field:
custom_fields.priority; - the found record:
find(person, "ivan@example.com "); - several records found:
find_all(ci, "server"); - full-text search result:
search(req, "printer"); - a newly created record:
new(task)ornew(task, template_name); - comparison, formula, ternary operator, or function.
A sign ! before referring to the value, inverts the boolean value if it supports a logical interpretation. For strings and other non-logical values, this does not turn the value into a text operation, but is used as a logical negation.
If the name is not found among the fields of the current record, previously calculated expressions, predefined values, and numbers, the system treats it as a static string. Therefore, fixed sets of predefined values are often written without quotation marks: status = completed.
The names of expressions cannot match reserved words and internal context keys. You cannot name the expression index, errors, or safe_attachments; predefined values and names that the condition language uses are also reserved.
Basic principles - type conversions and empty values
The system does not require the user to explicitly specify the types. When calculating, it brings the values to the desired form:
Boolean value: any non-empty value is considered true;
string: entries are displayed using an item, name, or display name, arrays of up to 100 items are separated by commas, large arrays are shown as the number of items;
number: Numeric strings, numbers, arrays, and records are reduced to a number according to internal rules;
Date/time: ISO8601 dates and times are recognized, as well as objects that support date/time;
Array: Regular arrays, ActiveRecord architectural pattern relationships, and deferred associations are supported.
An empty value usually stops further calculation and gives an empty result. Exceptions are specified: for example, empty? and blank? if the value is empty, "true" is returned.
Predefined values
Please note: if the name is not found as a field of the current record or as a previously calculated expression, the system checks a set of predefined values.
| Value | Result | Purpose |
|---|---|---|
now |
current date and time | used for calculations relative to the current moment |
today |
the current date | is used for calculations relative to the current day |
true |
the base boolean value is true |
the constant of truth |
false |
the base boolean value is false |
the lie constant |
empty |
a special empty string | is used to compare a value with an empty string |
nil |
empty result (zero) | the constant of the missing value |
null |
empty result (zero) | alternative to nil |
updated_by |
the person who made the change (the person who initiated the implementation of the automation rule by updating the record to which this automation rule applies) | is taken from the saved change context, the current user session, or the verification mode |
triggered_at |
the trigger time in UTC | is taken from the context of the rule execution; if there is none, the current moment is used |
rule_account |
rule space | the space where the automation rule is defined (to which the rule belongs) |
rule_app_instance |
the installed rule application | the application from which the rule came (if any) |
related_note |
linked comment (created when the automation rule was executed) | available for triggers related to adding a comment; if no comment was created, the value is empty; when using the "When adding a comment" trigger, this value is always present if the user responsible for automation has rights to read the comment |
related_internal_note |
related internal comment (an internal comment created when the automation rule was executed) | available for triggers related to adding an internal comment; if no comment has been created, the value is empty |
Important: at the top level of the expression, the name of the previously evaluated expression takes precedence over the field of the current record. Inside array functions, where an array element becomes the current object, the element fields are read before the name of the top-level expression.
Previous field values
The field ID can be used to find the value of this field. For example, to get the current value of the workflow Topic field, you can use the following expression:
- workflow.subject
However, you can also find the previous value of the record field, that is, the value that the field had before saving the record and triggering the automation rule.
This is done by adding _was after the field ID. For example, for the "Subject" field in the workflow, the expression looks like this:
- workflow.subject_was
The suffix _was refers to the value of the field at the time the rule was triggered.
The previous values are only available for the record that started the rule. Inside the array filter, they do not refer to the array element; in template validation mode, the system adds an error if *_was is used outside the top level.
| Syntax | Result | Purpose |
|---|---|---|
pole_was |
the previous value of the field | is used to compare the old and new state of the record |
custom_fields_was.code |
the previous value of the user field | used to check changes to user fields |
custom_data_was.code |
previous value of the user field | historical record option for user data |
Logical operators
Used for:
value A or value B
value A and value B
| Examples of expressions | Result |
|---|---|
| a or b (for example, if a is true, then b is either true or false) | true |
| a or b (for example, if b is true, then a is either true or false) | true |
| a or b (for example, a is false, and b is false) | false |
| a and b (for example, a is true and b is true) | true |
| a and b (for example, a is false, and/or b is false) | false |
Forms of expressions: Comparison - Equality
Used for:
value-A = value-B
value-A != value-B
| Syntax | Arguments | Result | Assignment |
|---|---|---|---|
left = right |
two values | true or false | checks for equality |
left != right |
two values | true or false | checks for inequality |
left < right |
two values | true or false | checks that the left value is less than the right |
left <= right |
two values | true or false | checks that the left value is less than or equal to the right |
left > right |
two values | true or false | checks that the left value is greater than the right |
left >= right |
two values | true or false | checks that the left value is greater than or equal to the right |
left contains right |
two values | true or false | checks whether the value is included |
left *= right |
two values | true or false | alternative to the contains operation |
left starts_with right |
two values | true or false | checks the beginning of a string or value |
left ^= right |
two values | true or false | alternative to the starts_with operation |
left ends_with right |
two values | true or false | checks the end of the string or values |
left $= right |
two values | true or false | alternative to the ends_with operation |
left is_blank |
one value | true or false | checks an empty value |
left is_present |
single value | true or false | checks for a non-empty value |
left in [value1, value2] |
value and array | true or false | checks that the value is included in the array |
left not_in [value1, value2] |
value and array | true or false | checks that the value is not in the array |
The array in in and not_in is written in square brackets. Array elements can be strings, value references, or other simple variables.
Comparisons bring values to a comparable form. Dates are compared as dates, numbers are compared as numbers, fixed sets of values are compared by position within their set, and the remaining values are compared as strings. For contains, the array is checked as a set of string representations of elements; for starts_with and ends_with, the first or last element on the array is checked, respectively.
Arrays support an empty array []. For backward compatibility, some unquoted string values with spaces are also allowed in array elements, but for new rules it is better to write strings in quotation marks.
| Examples of expressions | Result |
|---|---|
| 'text' = 'text' | true |
| 'text' != 'text' | false |
| '' = 'text' | false |
| 'text' = "" | false |
| " = "" | true |
| "a\"b" = 'a"b' | true |
| 'a\'b' = "a'b" | true |
| status = in_progress | true |
| status = assigned | false |
| team = 'Database Administration' | true |
| team = 9 | false |
| team.id = 9 | true |
| team.id = 12 | false |
Comparison - Less, More (examples)
Used for:
value-A < value-B
value-A <= value-B
value-A > value-B
value-A >= value-B
| Examples of expressions | Result |
|---|---|
| ‘a’ < ‘a’ | false |
| ‘a’ <= ‘a’ | true |
| ‘a’ > ‘a’ | false |
| ‘a’ >= ‘a’ | true |
| ‘a’ < ‘b’ | true |
| ‘b’ > ‘a’ | true |
| ‘a’ > ‘b’ | false |
| ‘’ < ’text’ | true |
| ‘text’ > ’ | true |
| status < completed | true |
| status < registered | false / |
| completed < status | false |
| registered <status | true |
| team < ‘Application Development’ | false / |
| team < ‘Service Desk’ | true |
| ‘Application Development’ <team | true |
| ‘Service Desk' < team | false / |
| team.id < 100 | true |
| team.id < 1 | false / |
| 100 < team.id | false |
| 1 < team.id | true |
Comparison - Contains (examples)
Used for:
the value in the array
the value is not in the array
| Examples of expressions | Result |
|---|---|
| a in [a,b] | true |
| a not_in [a,b] | false / |
| b in [a,b] | true |
| c in [a,b] | false |
| ab in [a,b] | false |
| ab in [] | false |
| ’ in [] | true |
| ’ in [a,b] | false |
| ’ in [a,,b] | true |
| a in [ a , b ] | true |
| status in [in_progress] | true |
| status in [assigned, accepted, in_progress, waiting_for_customer] | true |
| status in [assigned,completed] | false / |
| team in [Application Development,Database Administration,Service Desk] | true |
| team in [Application Development,Service Desk] | false |
| team.id in [8,9,10] | true |
| team.id in [11,12,13] | false |
| 11.0 in [11,12,13] | true |
| 11 in [11.0,12.0,13.0] | true |
| team.id in [8.0,9.0,10.0] | true |
| team.id in [8.1,9.1,10.1] | false |
Comparison is Similar (examples)
The operators are used:
* the ‘contains’ operator
^ the ‘starts_with’ operator
$ the 'ends_with’ operator
| Examples of expressions | Result |
|---|---|
‘ivan.ivanov@proproduct.ru’ *= ‘ivanov’ |
true |
‘ivan.ivanov@proproduct.ru’ ^= ‘ivanov’ |
false / |
‘ivan.ivanov@proproduct.ru ’ *= ‘ivan’ |
true |
‘ivan.ivanov@proproduct.ru’ ^= ‘ivan’ |
true |
‘ivan.ivanov@proproduct.ru’ $= ‘ivan’ |
false / |
‘ivan.ivanov@proproduct.ru ’ $= ‘proproduct’ |
false / |
‘ivan.ivanov@proproduct.ru ’ $= ‘proproduct.ru ’ |
true |
Comparison - Presence (examples)
Used for:
the value is empty
the value is present
| Examples of expressions | Result |
|---|---|
| team.name is_blank | false (the name of the command is required, as it must contain a value) |
| request.custom_fields.my_date is_present | true if the UI extension field "my_date" is defined and contains a non-empty value, false otherwise |
Formulas
The operators are used:
+ is an 'addition’ or ‘union’ operator
- the ‘subtraction’ operator
* the ‘multiplication’ operator
/ the division operator
% is the "multiplication modulo" operator
Note that the + sign acts as a "concatenation" operator if the value to the left of it is a text string. Otherwise, it acts as an "addition" operator.
| Syntax | Arguments | Result | Purpose |
|---|---|---|---|
left + right |
two values | number, string, date/time, duration or array | adds numbers, joins strings, adds seconds or duration to date/time, combines compatible arrays |
left - right |
two values | number, date/time or duration | subtracts numbers, subtracts seconds or duration from date/time, returns duration between two dates/time |
left * right |
two values | number | multiplies numeric values |
left / right |
two values | number or nil |
divides numeric values; returns an empty result when divided by zero |
left % right |
two values | number or nil |
returns the remainder of the division; returns an empty result when divided by zero |
left and right |
two values | boolean value (true/false) | logical And after converting both values to a logical form |
left or right |
two values | boolean value (true/false) | logical OR after converting both values to a logical form |
In the formula chain, the system takes into account the priority of the operators: %, then * and /, then + and -, then and, then or.
| Examples of expressions | Result |
|---|---|
1 + 1 |
2.0 |
2 – 1 |
1.0 |
2 * 5 |
10.0 |
6 / 3 |
2.0 |
15 % 6 |
3.0 |
1 1 1 + 1 |
4.0 |
1 + 2 * 6 % 4 |
5.0 |
‘start’ + ‘_at’ + ’ field’ |
the "start_at" field |
1 + team.name |
1.0 |
1 + team.id |
8.0 |
2.0 + team |
9.0 |
team + 3.0 |
10.0 |
created_at + 3.days |
3 days after the creation date |
team.id + ’ – ’ + team.name |
7.0 |
’ + team.id + ’ – ’ + team.name |
7 – Service Desk |
‘{{team_id}} – {{team_name}}’ |
7 – Service Desk |
created_at – 4.hours |
4 hours before the creation date |
5 / 5 |
1.0 |
5 / 0 |
zero (nil) |
The path to get the variable (the path of the value)
An expression that extracts a variable always starts with an entry for which an automation rule is defined.
After the initial value is set, you can add a path, for example:
1 request.requested_by.manager.name
2 requests[first].subject
3 find_all(ci, "server").select(status = in_production).map(name).join(", ")
| Syntax | Arguments | Result | Assignment |
|---|---|---|---|
.field |
the name of the field or connection to the record | the value of the field or the associated record | goes to the attribute or connection of the current value |
.custom_fields.The code |
user field code | user field value | reads user field from custom_fields |
.custom_data.code |
user field code | user field value | historical user data access option |
[first] |
no | the first element of the array | returns the first element of the collection |
[last] |
none | last element of the array | returns the last element of the collection |
[N] |
position number | array element | returns an element by position, positive positions are counted from 1, negative positions are counted from the end of the array |
[#ID] |
record ID | array element | searches the array for a record with the specified ID |
["name"] |
string | array element | searches the array for an entry by subject, if there is one, otherwise by name |
[expression] |
the name of an expression with a number or string | array element | uses the value of another expression as an index or name |
[N..M] |
two positions | part of the array | returns a range of elements; positive positions are counted from 1 |
If the index is not applied to an array, an empty result is returned when executing; when checking the template, the system adds a validation error.
The available fields depend on the type of record. The server restricts the list of allowed attributes for each type of record: for example, the request has a status, subject, person "requested by whom" (initiator) (requested_by), person "requested for" (requested_for), service component (service_instance), team, member), custom_fields, comments, tags, and other fields; in turn, the task has its own set. The full list of fields is large and is stored in the code as a whitelist; The syntax for accessing fields is described, rather than duplicating the entire whitelist by record type.
The path inside custom_fields / custom_data is not checked according to the UI extension scheme when evaluating the expression. When executing the rule, the system reads user fields as a key-value data structure (hash) and returns the value for the specified key; if there is no key, the result becomes empty. In the validation and template mode, the system does not know the active UI extension scheme for a specific field and considers the value of the user field to be a string.
Some of the old names are supported as an alternative for backward compatibility: the value of custom_data corresponds to the value of custom_fields; the value of change for the request and task corresponds to the workflow; the value of change_type corresponds to the value of workflow_type; the value of workflow_manager the service has the value of change_manager; the value of changes for a release corresponds to the value of workflows; the value of internal for a comment corresponds to the value of internal_account; the value of sitename for a space corresponds to its identifier.
Examples of using expressions are given below.
| Examples of expressions | Result |
|---|---|
| status | approved |
| workflow.status | progress suspended (progress_halted) |
| created_at | 2017-09-12T14:00:00Z |
| planned_duration | 8 |
| workflow.tasks[first] | 1st workflow task |
| workflow.tasks[1] | 1st workflow task |
| workflow.tasks[last] | last workflow task |
| workflow.tasks[-1] | last workflow task |
| workflow.tasks[#20122] | task with ID 20122 in the workflow |
| workflow.tasks[1].custom_fields.name | the value of the UI extension field with the identifier "name" from the workflow task |
| workflow.tasks[1].custom_fields.你好,世界 | value of the UI extension field with the identifier "你好,世界" from the workflow task |
| workflow.tasks[#20122].subject | Change controller approval |
| workflow.tasks[“Change controller approval”].id | 20122.0 |
| workflow.tasks[‘Change controller approval’] | 20122.0 |
| workflow.tasks[first].notes[first].text | text from the first comment of the first workflow task |
| workflow.tasks[first].notes[first].person.name | name of the person who added the first comment on the first workflow task |
Manipulating arrays
Array functions are applied to a collection or array separated by a dot. If the initial value is empty, most functions return an empty result; empty? returns "true".
| Function | Arguments | Result | Details |
|---|---|---|---|
. join("separator") |
separator string | string | converts each element of the array into a string and connects the elements with the specified separator |
.map(field) |
a reference to a field relative to an array element | an array of values | for each element calculates the specified field or path and returns an array of results; nested arrays are prohibited in verification mode |
.select(condition) |
binary comparison | array of elements | leaves elements for which the condition is true; the condition is calculated in the context of the current element of the array |
.reject(condition) |
binary comparison | array of elements | excludes elements for which the condition is true |
.detect(condition) |
binary comparison | single element or empty result | returns the first element for which the condition is true |
.any? |
no | boolean value (true/false) | checks for the presence of at least one element in the array |
.any?(condition) |
binary comparison | boolean value (true/false) | verifies that at least one element of the array satisfies the condition |
.all?(condition) |
binary comparison | boolean value (true/false) | verifies that all elements of the array satisfy the condition |
.none? |
no | boolean value (true/false) | checks that there are no elements in the array |
.none?(condition) |
binary comparison | boolean value (true/false) | checks that no element of the array satisfies the condition |
.empty? |
no | boolean value (true/false) | checks that the array is empty; returns "true" for an empty initial value |
.count |
no | number | returns the number of elements |
.count(condition) |
binary comparison | number | returns the number of elements satisfying the condition |
.size |
no | number | returns the number of elements |
.size(condition) |
binary comparison | number | works like count(condition): counts elements that satisfy the condition |
.sum |
no | number | converts elements to numbers and returns the sum |
.sum(condition) |
binary comparison | number | converts elements to numbers and summarizes those values for which the condition is true |
.min |
no | one element or an empty result | removes empty elements and returns the minimum value |
.max |
no | one element or an empty result | removes empty elements and returns the maximum value |
The size and empty functions? They can also work with a string, but they still refer to array functions if the syntax matches a massive function. When checking the type, the system distinguishes between a string and a collection. The condition for sum(condition) is applied after the elements have been converted to numeric form; if you need to filter records by fields, it is better to use select(condition) first, then map(numeric field) and only after that sum.
The path to retrieve the collection (examples)
An expression retrieving a collection always starts with an entry for which an automation rule is defined, or uses the find_all operation.
| Examples of expressions | Result |
|---|---|
| cis | All CIs related to the current task |
| workflow.requests[first].cis | All requests related to the first workflow request |
| cis.size | The number of CIs associated with the current task |
| cis.count | The number of CIs associated with the current task |
| workflow.tasks.select(status = registered) | Workflow tasks with the status "Registered" |
| workflow.tasks.reject(status = registered) | Workflow tasks that do not have the "Registered" status |
| workflow.tasks.select(status = failed) + workflow.tasks.select(status = rejected) | Workflow tasks with the status "Failed" in combination with workflow tasks with the status "Rejected" |
| cis.empty? | True if no CIs are attached to the current task, false otherwise |
| cis.any? | True if at least one CIs is linked to the current task, false otherwise |
| cis.any?(status = in_production) | True if any CIs with the status in production are attached to the current task, false otherwise. Returns false if no CIs are associated with the task |
| cis.all?(status = in_production) | True if all CIs related to the current task have the status "in production", false otherwise. Returns `true' if no keys are associated with the task |
| cis.none?(status = in_production) | True if the current task is not associated with the status "in production", false otherwise. Returns `true' if the task is not linked to |
| workflow.tasks.select(category = approval).reject(finished_at != nil) | All approval tasks related to the workflow that have not yet been completed |
| workflow.tasks.select(category = implementation).map(member) | All participants in the implementation tasks related to the workflow |
| person.permissions.detect(account = ‘dc’).workflow_manager | Is this person a workflow manager in the data center space? |
Searching and creating records, including extracting unrelated records
The following functions are available for searching and retrieving records that are not related to the record for which the automation rule is defined, as well as for creating records.
These functions are used as the initial value of the expression up to the point and the path functions.
| Syntax | Arguments | Result | Assignment |
|---|---|---|---|
find(type, value) |
record type, number, or string | one record or an empty result | searches for one record of an available type based on a specific source value |
find_all(type, value) |
record type, number, string, or array of numbers/rows | record array | searches for all suitable records of the available type |
search(type, string) |
record type, search string | array of records, maximum 50 | performs a full-text search for user-accessible records of the specified type |
new(task) |
the type of record being created | new task | creates a new task in memory for further filling with actions |
new(task, template) |
type of record being created, name/ID/template record | new task with the applied template | creates a new task and applies the found task template |
For find and find_all, the request model is converted to a request, and the historical name change is converted to a workflow. The search is not available for Account (space) and Customer (customer), as well as for types that do not have allowed attributes or substitution columns.
For search, the type must support global search. The results are additionally filtered by the user's viewing access.
The value of new currently supports only the creation of tasks. If a template is passed, the template value must be a number, a string, or a found record of the task template.
Search examples.
| Examples of expressions | Result |
|---|---|
| find(person, ‘singileeva.klavdiya@pro-product.ru ’) | Claudia Singileeva |
| find(person, ‘singileeva.klavdiya@pro-product.ru’).job_title | Position of Klavdia Singileeva |
| find(person, workflow.requests[first].custom_fields.email) | A record of a person based on the email address specified in the email field of the UI extension of the first workflow-related request |
| find(service_instance, 2334) | Service instance with ID 2334 |
| find(service_instance, ‘Minsk Network’) | An instance of the Minsk Network service |
| find(ci, precursors[first].custom_fields.ci_id) | Searching for a CIs based on the CIs ID selected in the UI extension of the previous task |
| find(ci, ‘unknown') | Zero (nil) |
| find_all(person, ‘Singileeva Klavdiya’) | List of all persons with the name of Klavdi Singileyev |
| find_all(ci, custom_fields.impacted_assets) | An array of all CIs selected in the UI extensions field with multiple answer options |
| search(ci, ‘SPARCS’).detect(status = in_production) | An array of all CIs in operation from a list containing no more than 50 items obtained using a global search for the keyword "SPARCS". |
Examples of creating new records (for tasks only).
| Examples of expressions | Result |
|---|---|
| new(task) | A new empty task has appeared in the rule space |
| new(task, ‘Finalize the change plan') | A new task based on the provided template |
String manipulation
String functions convert the original value to a string, with the exception of the to_date_time function, which converts the value to a date/time. If the original value is empty, empty? and blank? return "true", present? returns "false", the other functions return an empty result.
| Function | Arguments | Result | Details |
|---|---|---|---|
. size |
no | number | returns the length of the string |
.length |
no | number | returns the length of the string |
.strip |
no | line | removes spaces at the beginning and end of the line |
.lstrip |
no | line | removes spaces at the beginning of the line |
.rstrip |
no | line | removes spaces at the end of the line |
.squish |
no | line | removes extreme spaces and compresses sequences of spaces inside the line |
.squeeze |
no | string | compresses duplicate characters according to the rules of the Ruby string operation |
.reverse |
no | string | returns the string in reverse order |
.upcase |
no | string | converts the string to uppercase |
.downcase |
no | string | lowercases the string |
.swapcase |
no | string | reverses the letter case |
.capitalize |
no | string | capitalizes the first letter and lowercases the rest |
.titleize |
no | string | brings words to the form with the uppercase first letter without removing characters from the result |
.empty? |
no | boolean value (true/false) | checks an empty string |
.blank? |
no | boolean value (true/false) | checks for an empty string or a string of spaces |
.present? |
no | boolean value (true/false) | checks a non-empty value |
.to_number |
no | number | converts a string to a floating-point number |
.to_date_time |
no | date/time or an empty result | converts an ISO8601 date or ISO8601 time to a date/time |
.split("separator") |
string | array of strings | splits the string according to the specified separator |
.split(/regular expression/) |
regular expression | array of strings | splits a string according to a regular expression |
.match?("string") |
string | boolean value (true/false) | checks for a match with the string as with an escaped pattern |
.match?(/regular expression/) |
regular expression | boolean value (true/false) | checks for a regular expression match |
.start_with?(value) |
value | boolean value (true/false) | checks that the string starts with the passed value |
.end_with?(value) |
value | boolean value (true/false) | checks that the string ends with the passed value |
.include?(value) |
value | boolean value (true/false) | checks that the string contains the passed value |
.exclude?(value) |
value | boolean value (true/false) | checks that the string does not contain the passed value |
.slice(N) |
number | string | returns the part of the string from position N to the end; the positive position is counted from 1 |
.slice(N, length) |
two numbers | string | returns the part of the string from the N position of the specified length; the positive position is counted from 1 |
.ljust(length) |
number | string | complements the string on the right with spaces up to the specified length |
.ljust(length, placeholder) |
number and value | string | complements the string on the right with the specified placeholder |
.rjust(length) |
number | string | complements the string on the left with spaces up to the specified length |
.rjust(length, placeholder) |
number and value | string | complements the string on the left with the specified placeholder |
.replace("what", "what") |
string and string | string | replaces all occurrences of the first string with the second |
.replace(/regular expression/, "for what") |
regular expression and string | string | replaces all regular expression matches with the second string |
String arguments in quotation marks are interpolated by the rule values. Regular expressions are executed with a limit of 4 seconds; if the limit is exceeded, the system adds an execution error and returns an empty result.
The following are examples of string manipulation in automation rules.
| Examples of expressions | Result |
|---|---|
| ’hello’.lstrip | Removes the initial space (‘hello’). |
| ’hello ’.rstrip | Removes spaces at the end of the string (‘hello’). |
| ‘hello’.start_with?(‘hell’) | The truth. True if the string starts with one of the specified suffixes. |
| ‘hello’.end_with?(‘lo’) | The truth. True if the string ends with one of the specified suffixes. |
| ‘table’.match?(‘bl’) | True. The value is "True" if the pattern is found in the string. |
| s=‘foo’, s.include?(‘f’) | True. True if self contains another string. |
| s=‘foo’, s.exclude?('t’) | True. True if self does not contain another string. |
| ‘hello’.ljust(10) | If an integer is longer than the length of the string, returns a string with left padding. |
| ‘hello’.rjust(10, ‘oh’) | If the integer is greater than the length of the string, returns a right-aligned string with padding. |
| subject.size | Number of characters is 28. |
| subject.length | Number of characters is 28. |
| ’spacey string ’.strip | Remove the leading and ending spaces. |
| ’spacey string ’.squish | Replace multiple spaces with a single space and remove the leading and ending spaces. |
| ’spaceeeey ssstring ’.squeeze | Replace sequences of identical characters with a single character. |
| ‘desserts'.reverse | Swap characters (‘stressed’). |
| ‘r-service’.upcase | All letters are uppercase. |
| ‘R-SERVICE’.downcase | All letters are lowercase. |
| ‘hI tHERE’.swap | Lowercase letters to uppercase and vice versa (‘Hi There’). |
| ’ ’.empty? | The truth. Returns "true" if the string is empty or contains only spaces. |
| ’ ’.blank? | The truth. Returns "true" if the string is empty or contains only spaces. |
| ’ ’.present? | Lies. Returns "true" if the string contains characters other than spaces. |
| ‘break-me-up'.split(‘-’) | Split a string into an array of strings by separator ([‘break’, ‘me’, ‘up’]). |
| ‘break-me-up’.split(/[eau]+/) | Split a string into an array of strings using the separator regular expression ([‘br’, ‘k-m’, ‘-’, ‘p’]). |
| ‘break-me-up'.slice(3) | Take a line starting from the specified file index.md and then (‘eak-me-up’). |
| ‘break-me-up'.slice(-5) | Take a line starting from the specified file index.md and then (‘me-up’). |
| ‘break-me-up'.slice(3,2) | Take a fixed number of characters from a given file index.md (‘ea’). |
| ‘break-me-up'.replace(‘-’, ’ ’) | Replace all occurrences with another string (‘break me up’). |
| ‘break-me-up’.replace(/[eau]+/, ‘*’) | Replace all occurrences of regular expression with another string (‘br*k-m*-*p’). |
| ‘break-me-up'.replace(/([eau]+)/, ‘\1’) | Replace all occurrences of regular expression with another string using capture groups (‘br*ea*k-m*e*-*u*p’). |
| [‘break’,‘me’,‘up’].join(’and ’) | Combine the array elements using the specified separator (‘break and me and up’). |
| ‘10.428571428571429'.to_number | Convert string to number (10.428571428571429). |
Manipulating numbers
Numeric functions convert the original value to a number. If the value is empty, the function returns an empty result.
| Function | Arguments | Result | Details |
|---|---|---|---|
.round |
no | number | rounds a number to an integer |
.round(precision) |
number | number | rounds the number to the specified number of digits |
.to_string |
no | string | converts a number to a string |
The following are examples of usage in automation rules.
| Examples of expressions | Result |
|---|---|
| 10.428571428571429.to_string | Convert a number to a string (‘10.428571428571429’). |
| 10.428571428571429.round | Rounding to an integer (10). |
| 10.428571428571429.round(2) | Rounding to the specified number of decimal places (10.43). |
Date and time manipulation
| Syntax | What | Result | is applied to Purpose |
|---|---|---|---|
.seconds / .second |
number | duration | interprets the number as seconds |
.minutes / .minute |
number | duration | interprets the number as minutes |
.hours / .hour |
number | duration | interprets the number as hours |
.days / .day |
number | duration | interprets the number as days |
.weeks / .week |
number | duration | interprets the number as weeks |
.months / .month |
number | duration | interprets the number as months |
.years / .year |
number | duration | interprets the number as years |
.ago |
number or duration | date/time | subtracts the duration from the current moment; if there is a number on the left, it is considered seconds |
.from_now |
number or duration | date/time | adds the duration to the current moment; if there is a number on the left, it counts as seconds |
.is_monday ... .is_sunday |
date/time | boolean value (true/false) | checks the day of the week |
.year, .month, .day |
date/time | number | returns year, month, or day |
.hour, .minute, .second |
date/time | number | returns hour, minute, or second |
.day_of_week |
date/time | number | returns the number of the day of the week |
.day_of_year |
date/time | number | returns the number of the day in the year |
.utc |
date/time | date/time | returns the same instant in Coordinated Universal Time (UTC) |
.in_time_zone(hours) |
a string or value that gives the string | date/time | translates the date/time to the specified time zone; if the time zone is unknown, it adds an error |
| .iso8601` | no | string | returns the date/time in the ISO8601 standard format |
Please note: Some values support dot-separated attributes, although they are not domain record fields.
Please note: date and time functions .in_time_zone(clock_time) and .iso8601 first try to bring the original value to the date/time. Strings are recognized only in the ISO8601 date (YYYY-MM-DD) or ISO8601 time format.
The following are examples of usage in automation rules.
| Examples of expressions | Result |
|---|---|
| now | >1.seconds ago <1.seconds from now (>1.seconds.ago <1.seconds.from_now) |
| today | >1 day ago <1 day from now (>1.day.ago <1.day.from_now) |
| 1.second.ago | >2 seconds ago <0 seconds from now (>2.seconds.ago <0.seconds.from_now) |
| 2.seconds.ago | >3 seconds ago <1 second ago (>3.seconds.ago <1.second.ago) |
| 1.minute.ago | >61 seconds ago <59 seconds ago (>61.seconds.ago <59.seconds.ago) |
| 2.minutes.ago | >121 seconds ago <119 seconds ago (>121.seconds.ago <119.seconds.ago) |
| 1.hour.ago | >61 minutes ago <59 minutes ago (>61.minutes.ago <59.minutes.ago) |
| 2.hours.ago | >121 minutes ago <119 minutes ago (>121.minutes.ago <119.minutes.ago) |
| 1.day.ago | >25 hours ago <23 hours ago (>25.hours.ago <23.hours.ago) |
| 2.days.ago | >49 hours ago <47 hours ago (>49.hours.ago <47.hours.ago) |
| 1.week.ago | >8 days ago <6 days ago (>8.days.ago <6.days.ago) |
| 2.weeks.ago | >15 days ago <13 days ago (>15.days.ago <13.days.ago) |
| 1.month.ago | >32 days ago <27 days ago (>32.days.ago <27.days.ago) |
| 2.months.ago | >63 days ago <56 days ago (>63.days.ago <56.days.ago) |
| 1.year.ago | >366 days ago <364 days ago (>366.days.ago <364.days.ago) |
| 2.years.ago | >732 days ago <729 days ago (>732.days.ago <729.days.ago) |
| 1.second.from_now | >0.seconds.from_such <2.seconds.from now (>0.seconds.from_now <2.seconds.from_now) |
| 2.seconds.from_now | >1.seconds.from_such <3.seconds.from now (>1.seconds.from_now <3.second.from_now) |
| 1.minute.from_now | >59.seconds.from_such <61.seconds.from now (>59.seconds.from_now <61.seconds.from_now) |
| 2.minutes.from_now | >119.seconds.from_such <121.seconds.from now (>119.seconds.from_now <121.seconds.from_now) |
| 1.hour.from_now | >59 minutes from now <61 minutes from now (>59.minutes.from_now <61.minutes.from_now) |
| 2.hours.from_now | >119 minutes from now <121 minutes from now (>119.minutes.from_now <121.minutes.from_now) |
| 1.day.from_now | >23.hours.from_such <25.hours.currently (>23.hours.from_now <25.hours.from_now) |
| 2.days.from_now | >47.hours.currently <49.hours.currently (>47.hours.from_now <49.hours.from_now) |
| 1.week.from_now | >6.days.from_such <8.days.from now (>6.days.from_now <8.days.from_now) |
| 2.weeks.from_now | >13.days.from_such <15.days.from now (>13.days.from_now <15.days.from_now) |
| 1.month.from_now | >27 days from now <32 days from now (>27.days.from_now <32.days.from_now) |
| 2.months.from_now | >56.days.from_such <63.days.from now (>56.days.from_now <63.days.from_now) |
| 1.year.from_now | >364.days.currently <366.days.from now (>364.days.from_now <366.days.from_now) |
| 2.years.from_now | >729.days.currently <732 days.from now (>729.days.from_now <732.days.from_now) |
| planned_duration.hours.from_now | >79.hours.currently <81.hours.currently (>79.hours.from_now <81.hours.from_now) |
| now.year | Year, for example, 2019 |
| now.month | Month of the year, for example, the third (March) |
| now.day | Day of the month, for example, 21 |
| now.hour | Hour of the day, for example, 19 |
| now.minute | Minute of the hour, for example, 45 |
| now.second | Second of a minute, for example, 12 |
| now.day_of_year | Day of the year, for example, 80 |
| now.day_of_week | Day of the week, for example, 4 (Thursday) |
| now.is_monday | The day is Monday, for example, false |
| now.is_tuesday | The day is Tuesday, for example, false |
| now.is_vednesday | The day is Wednesday, for example, false |
| now.is_thursday | The day is Thursday, for example, false |
| now.is_friday | The day is Friday, for example, false |
| now.is_saturday | The day is Saturday, for example, false |
| now.is_sunday | The day is Sunday, for example, false |
| now.utc | The date and time match in the UTC time zone |
| custom_fields.my_date_time.to_date_time | Convert string date and time value obtained from custom fields to date and time format |
| now.in_time_zone(person.time_zone) | The date and time match in the person's time zone |
| now.in_time_zone(rule_account.time_zone) | The date and time match the time zone of the space in which the rule was created |
| now.in_time_zone(‘Minsk’) | The same date and time in the specified time zone |
| now.iso8601 | The same date and time in the ISO8601 standard format |
| duration(created_at, now) | The number of minutes between creation and the current moment |
| template.support_hours.target_at(now, 8.hours, ‘Moscow’) | Target date calculated based on support hours from the request template, start time and duration, for the Moscow time zone |
Calendar manipulation
Calendar functions are applied to a value of the calendar type. If the original value is not a calendar, the function returns an empty result, and when checking the rule, the system adds an error.
| Function | Arguments | Result | Details |
|---|---|---|---|
.target_at(start, duration) |
date/time, number, or duration value | date/time | calculates the target time according to the calendar: adds the working duration from the start time; the duration is passed in seconds and converted into minutes inside the function |
.target_at(start, duration, time zone) |
date/time, duration, time zone string | date/time | same, but with a specific time zone |
.duration(beginning, end) |
two dates/times | number | calculates the working duration between two calendar points |
.duration(start, end, time zone) |
two dates/times, time zone string | number | the same, but with a specific time zone |
If no time zone is specified, the time zone of the automation rule space is used. If the transmitted time zone is unknown, the system adds an error and returns an empty result.
Ternary statements are ternary operators
| Syntax | Arguments | Result | Assignment |
|---|---|---|---|
| condition ? if yes : if there is | a condition and two values | one of the two values | returns the second value if the condition is non-empty, otherwise the third |
| condition then if else if not | condition and two values | one of the two values | alternative notation of the ternary operator |
When checking the rule in template mode, both results must have a compatible type. For example, you can't return a record in one branch and an array of records in another.
| Examples of expressions | Result |
|---|---|
| true then ‘yes’ else ‘no’ | yes (‘yes’) |
| !true then ‘yes’ else ‘no’ | no (‘no’) |
| is_assigned then teamA.id else teamB.id | id of team A, if is_assigned is true |
| true ? ‘yes’ : ‘no’ | yes (‘yes’) |
| !true ? ‘yes’ : ‘no’ | no (‘no’) |
| is_assigned ? teamA.id : teamB.id | id of team A, if is_assigned is true |
String interpolation
You can use expressions within expressions. However, an expression can only be used if it is already defined, so the order of the expressions is important. The example below works because the expression "note" is defined before it is used in the expression "hello_note":
- note: notes[last]
- hello_note: “hello {{note}}”
You can change the order of expressions by dragging them up or down to ensure that each expression is defined before it is used in another expression.
Suggestions from the Rule Editor
The rule editor gets lists of functions, operators, predefined values, types, and allowed fields from the server metadata. Therefore, the names of the functions in the hints correspond to the server constants: if the function is in array_functions, string_functions, number_functions, date_time_functions or calendar_functions, the editor can show it in the appropriate place of the expression.
The hints depend on the specific type of the current value.:
- Array functions are shown only for collection values;
- string functions - for strings only;
- numeric functions - for integers and fractions;
- Date/time functions - for date, time, and types of accurate date/time capture of an event;
- Calendar functions - only for calendar;
find,find_all,searchandneware shown at the beginning of the value if the current position is not inside another function of the same type.;- Hints for
_wasare built from allowed fields of the current type and are not shown for collection fields.
However, there may be some discrepancies.:
| Script | Server | Editor |
|---|---|---|
start_with?(...), end_with?(...), include?(...), exclude?(...) |
The argument can be a variable. | Parameter validation accepts a string in quotes or a regular expression, as for split / match?. The variable may be highlighted as an editor error. |
ljust(length, placeholder), rjust(length, placeholder) |
The second argument can be a variable. | The second argument is accepted as a string in quotation marks. |
target_at(start, duration) |
The second argument can be a variable or an integer, and the runtime converts the value to a number. | The editor check expects an integer type for the second argument. |
Models for find, find_all, search |
The runtime additionally prohibits some types: for example, find(account, ...) and find(customer, ...) unavailable. |
Model name hints can show the type that the runtime will reject later. |
| Parentheses for array functions without parameters | Allowed any?, none?, empty?, count, size, sum, min, max without parameters; the filter is allowed only for some functions. |
The editor shows all the names from the server list. If the user manually adds brackets to the function without a filter, the highlight may not match the server data. |
Thus, the function names of the editor's suggestions are synchronized with the server, but the editor is not an exact copy of all the options for arguments. In a dispute, the server and the nodes of the expression runtime remain the source of truth.