AppConnect Data Types and Formulas: Array/hash (list)

Lists and hashes

When you work with formulas and repeating structures, there are 2 key data structures you need to understand: arrays (lists) and hashes. Take note that most formulas will return an error and stop the job if it tries to operate on nulls (expressed as nil in Ruby), except for present?presence and blank?.

Lists (arrays)

Arrays are ordered, integer-indexed collections of any object. List indexing starts at 0. Lists are the same as Ruby arrays, and we will be using lists and arrays interchangeably in this article.

Let's take the example of a list with 4 list items: 100, 101, 102, 103. This list is expressed as:

1number_list = [100, 101, 102, 103, 104]2

As lists are ordered, we can use the following formula to get the values. AppConnect only supports retrieving up to the fifth item in the list:

Formula

Result

number_list.first

100

number_list.second

101

number_list.third

102

number_list.fourth

103

number_list.fifth

104

number_list.last

104

We can also use indexes to get corresponding values. Remember, indexes start at 0:

Formula

Result

number_list[0]

100

number_list[1]

101

number_list[2]

102

number_list[3]

103

Lists in Ruby supports negative indexes.

Formula

Result

number_list[-1]

104

number_list[-2]

103

number_list[-3]

102

number_list[-4]

101

Lists also support ranges as indexes. This returns another list, instead of returning only a value.

Formula

Result

number_list[0..2]

[100, 101, 102]

number_list[-3..-1]

[102, 103, 104]

number_list[0..-2]

[100, 101, 102, 103]

Hashes

A hash is a dictionary-like collection of unique keys and their values. They are similar to Lists, but where a List uses integers as its index, a Hash allows you to use any object type. Hashes enumerate their values in the order that the corresponding keys were inserted.

Let's take the example of a hash with 2 values, with 'Acme widgets' and 10 as the values of item_name and item_quantity respectively.

1line_item = { 'item_name' => 'Acme widgets', 'item_qty' => 10 }2

Formula

Result

line_item["item_name"]

"Acme widgets"

line_item["item_qty"]

10

List of hashes

In AppConnect, you will mostly run into lists of hashes. Let's look at a Quickbooks invoice which has a number of line items. It will be represented as an list of hashes.

1line_items = [ # list2 { 'item_name' => 'Acme widgets', 'item_qty' => 10 }, # hash 13 { 'item_name' => 'RR bearings', 'item_qty' => 100 }, # hash 24 { 'item_name' => 'Coyote tyres', 'item_qty' => 7 } # hash 35]6

Formulas

AppConnect supports a variety of list formulas. Formulas in AppConnect are whitelisted Ruby methods, and therefore not all Ruby methods are supported. You can always reach out to us to add additional formulas to the whitelist. Syntax and functionality for these formulas are generally unchanged.

Example list of hashes

The following is an example of a list of hashes called Contacts.

This is the Contacts list in a table form:

name

email

state

company

company_rev

Joe

joe@abc.om

CA

ABC

1000

Jill

jill@nbc.com

MA

NBC

1000

Joan

joan@nbc.com

MA

NBC

10000

Jack

jack@hbo.com

CA

HBO

30000

This is the Contacts list in a list of hashes form.

1[2 {3 'name' => 'Joe',4 'email' => 'joe@abc.com',5 'state' => 'CA',6 'company' => 'ABC',7 'company_rev' => 1000,8 'description' => { 'summary' => 'First time buyer', 'estimated_value' => 300 }9 },10 {11 'name' => 'Jill',12 'email' => 'jill@nbc.com',13 'state' => 'MA',14 'company' => 'NBC',15 'company_rev' => 1000,16 'description' => { 'summary' => 'Referral', 'estimated_value' => 500 }17 },18 {19 'name' => 'Joan',20 'email' => 'joan@nbc.com',21 'state' => 'MA',22 'company' => 'NBC',23 'company_rev' => 10000,24 'description' => { 'summary' => 'Recurring customer', 'estimated_value' => 900 }25 },26 {27 'name' => 'Jack',28 'email' => 'jack@hbo.com',29 'state' => 'CA',30 'company' => 'HBO',31 'company_rev' => 30000,32 'description' => { 'summary' => 'Recurring customer', 'estimated_value' => 1000 }33 }34]35

first

This formula returns the first item in a list.

It can also be used to return the first n items in a list. In this case, the output will be formatted as a list.

Syntax

List.first(number)

  • List - An input list.

  • number - (optional) The number of items to retrieve from the list. If not specified, the formula will return only one item.

Sample usage

Formula

Result

["One","Two","Three","Four","Five"].first()

"One"

["One","Two","Three","Four","Five"].first(2)

["One","Two"]

[1,2,3,4,5].first()

1

[1,2,3,4,5].first(3)

[1,2,3]

How it works

This formula returns the first n items from a list. If n is greater than one, the output is formatted as a list.

If you are returning a single item (i.e. no arguments provided). The output will be formatted according to the item's datatype.

If you are returning more than one item. The output will be formatted as a list datatype.

 


last

This formula returns the last item in a list.

It can also be used to return the last n items in a list. In this case, the output will be formatted as a list.

Syntax

List.last(number)

  • List - An input list.

  • number - (optional) The number of items to retrieve from the list. If not specified, the formula will return only one item.

Sample usage

Formula

Result

["One","Two","Three","Four","Five"].last()

"Five"

["One","Two","Three","Four","Five"].last(2)

["Four","Five"]

[1,2,3,4,5].last()

5

[1,2,3,4,5].last(3)

[3,4,5]

How it works

This formula returns the last n items from a list. If n is greater than one, the output is formatted as a list.

If you are returning a single item (i.e. no arguments provided). The output will be formatted according to the item's datatype.

If you are returning more than one item. The output will be formatted as a list datatype.

 


index

Returns the index of the first item matching the given value.

Syntax

Input.index(value)

  • Input - An input list.

  • value - The value to search for in the list.

Sample usage

Formula

Result

[4, 5, 6, 7].index(6)

2

[4, 5, 6, 7].index(8)

nil


where

Retrieves only the rows (hashes) which satisfy the specified WHERE condition. This formula accepts a single argument in the form of a hash with one or more key-value pairs.

The default operand for the condition is equal to (==). This formula also supports the following operands. Operands should be added to the end of key separated by a space.

Name

Notation

Example

Equal to (default)

==

leads.where('state': 'CA')

More than

>

leads.where('company_revenue >": 10000)

More than or equal to

>=

leads.where('company_revenue >=": 10000)

Less than

<

leads.where('company_revenue <": 10000)

Less than or equal to

<=

leads.where('company_revenue <=": 10000)

Not equal to

!=

leads.where('state !=': 'CA')

Use datapills as the conditional argument

Instead of using a static value (e.g. 'CA'), you can use a datapill as the conditional argument. The value of the datapill will be processed at run-time.

contacts.where(state: datapill )

Sample usage

Example of a single where conditionExample of compound where formulaExample of multiple matchesExample where condition with pattern matchingExample where condition with pattern matching (using datapills)Example of chaining where conditions


except

Returns a hash that includes everything except given keys.

1hash = { a: true, b: false, c: nil }2hash.except(:c) # => { a: true, b: false }3hash.except(:a, :b) # => { c: nil }4hash # => { a: true, b: false, c: nil }5

pluck

Retrieves only the columns which have been specified.

Sample usage

Example of a single column dataputExample of a multiple column datasetExample of retrieving nested fields


format_map

Create an array of strings by formatting each row of given array of hashes. Allows you to add static text to the created strings as well. Fields to be represented in the format %{<field_name>}.

Sample usage

contacts.format_map('Name: %{name}, Email: %{email}, Company: %{company}') returns

1[2 'Name: Joe, Email: joe@abc.com, Company: ABC' ,3 'Name: Jill, Email: jill@nbc.com, Company: NBC' ,4 'Name: Joan, Email: joan@nbc.com, Company: NBC' ,5 'Name: Jack, Email: jack@hbo.com, Company: HBO' ,6]7

The above example will give you a list of strings, one string for each row of the list "contacts", using data from 3 of the fields: name, email and company, as stated.


join

Combines all items in a list into a text string. A separator is placed between each item.

Syntax

List.join(separator)

  • List - An input of list datatype.

  • separator - The character to add between items when they are joined. If no separator is specified, the list items will be joined together.

Sample usage

Formula

Result

["Ms", "Jean", "Marie"].join("-")

"Ms-Jean-Marie"

[1,2,3].join("--")

"1--2--3"

["ab", "cd", "ef"].join

"abcdef"

How it works

The list items are combined into a single text string. The seperator character(s) is added between each item.

Seperator character

You can use a string of characters together as the seperator argument (e.g. ", ").

["Open","Pending","Closed"].split(", ") returns "Open, Pending, Closed".

 


smart_join

Joins list elements into a string. Removes empty and nil values and trims any white space before joining.

Syntax

List.smart_join(separator)

  • List - An input of list datatype.

  • separator - The character to add between items when they are joined. If no separator is specified, a blank space will be used as the joining character.

Sample usage

Formula

Result

[nil, "", "Hello", " ", "World"].smart_join(" ")

"Hello World"

["111 Vinewood Drive", "", "San Francisco", "CA", "95050"].smart_join(",")

"111 Vinewood Drive, San Francisco, CA, 95050"


reverse

Reverses the order of a list.

Syntax

List.reverse

  • List - An input of list datatype.

Sample usage

Formula

Result

["Joe", "Jill", "Joan", "Jack"].reverse

["Jack", "Joan", "Jill", "Joe"]

[100, 101, 102, 103].reverse

[103, 102, 101, 100]


sum

For integers and decimals, the numbers will be added together and the total sum obtained. For strings, the strings will be concatenated together to form a longer string.

Syntax

List.sum

  • List - An input of list datatype.

Sample usage

Formula

Result

[1, 2, 3].sum

6

[1.5, 2.5, 3].sum

7.0

["abc", "xyz"].sum

"abcxyz"


uniq

Returns a list containing unique items i.e. remove duplicate items.

Syntax

List.uniq

  • List - An input of list datatype.

Sample usage

Formula

Result

["joe", "jack", "jill", "joe", "jack"].uniq

["joe","jack", "jill"]

[1, 2, 3, 1, 1, 3].uniq

[1, 2, 3]

[1.0, 1.5, 1.0].uniq

[1.0, 1.5]


flatten

Flattens a multi-dimensional array (i.e. array of arrays) to a single dimension array.

Syntax

List.flatten

  • List - An input of list datatype.

Sample usage

Formula

Result

[[1, 2, 3], [4, 5, 6]].flatten

[1, 2, 3, 4, 5, 6]

[[1, [2, 3], 3], [4, 5, 6]].flatten

[1, 2, 3, 3, 4, 5, 6]

[[1, [2, 3], 9], [9, 8, 7]].flatten

[1, 2, 3, 9, 9, 8, 7]


length

Returns the number of elements in self. Returns 0 if the list is empty.

Syntax

List.length

  • List - An input of list datatype.

Sample usage

Formula

Result

[ 1, 2, 3, 4, 5 ].length

5

[{..}, {..}, {..}].length

3

[" ", nil, "", nil].length

4

[].length

0


max

Returns largest value in an array. When comparing numbers, the largest number is returned. When comparing strings, the string with the largest ASCII value is returned.

Syntax

List.max

  • List - An input of list datatype.

Sample usage

Formula

Result

[-5, 0, 1, 2, 3, 4, 5].max

5

[-1.5, 1.5, 2, 3, 3.5].max

3.5

["cat", "dog", "rat"].max

"rat"


min

Returns smallest value in an array. When comparing numbers, the smallest number is returned. When comparing strings, the string with the smallest ASCII value is returned.

Syntax

List.min

  • List - An input of list datatype.

Sample usage

Formula

Result

[-5, 0, 1, 2, 3, 4, 5].min

-5

[-1.5, 1.5, 2, 3, 3.5].min

-1.5

["cat", "dog", "rat"].min

"cat"


compact

Removes nil values from array and hash.

Sample usage

Formula

Result

["foo", nil, "bar"].compact

["foo", "bar"]

{ foo: 1, bar: nil, baz: 2 }.compact

{ foo: 1, baz: 2 }


Conditionals

blank?

This formula checks the input string and returns true if it is an empty string or if it is null.

Syntax

Input.blank?

  • Input - An input datapill. It can be a string, number, date, or datetime datatype.

Sample usage

Formula

Result

"Any Value".blank?

false

123.blank?

false

0.blank?

false

"".blank?

true

How it works

If the input is null or an empty string, the formula will return false. For any other data, it returns true.

 


include?

Checks if the string contains a specific substring. Returns true if it does.

Syntax

Input.include?(substring)

  • Input - A string input.

  • substring - The substring to check for.

Sample usage

Formula

Result

"Partner account".include?("Partner")

true

"Partner account".include?("partner")

false

How it works

This formula check is the string contains a specific substring. Returns true if it does, otherwise, returns false. This substring is case sensitive.

This function acts in an opposite manner from exclude?. It will return true only if the input string contains the stated keyword.

 


present?

This formula will check the input and if there is a value present, it will return true. If the input is nil, an empty string or an empty list, the function will return false.

Syntax

Input.present?

  • Input - An input datapill. It can be a string, number, date, or list datatype.

Sample usage

Formula

Result

"Any Value".present?

true

123.present?

true

0.present?

true

"2017-04-02T12:30:00.000000-07:00".present?

true

nil.present?

false

"".present?

false

[].present?

false

How it works

If the input is null, an empty string or an empty list, the formula will return false. For any other data, it returns true.

Evaluating a list with nil values

  • Only an empty list will return false.

[].present? returns false.

  • A list with nil and empty string will return true.

[nil,""].present? returns true.

 


presence

Returns the data if it exists, returns nil if it does not.

Syntax

Input.presence

  • Input - An input datapill. It can be a string, number, date, or datetime datatype.

Sample usage

Formula

Result

nil.presence

nil

"".presence

nil

"Any Value".presence

"Any Value"

45.0.presence

45.0

0.presence

0

How it works

If the input is null or an empty string, the formula will return nil. For any other data, it returns the orignal input data.

Conversion

The following formulas allow you to convert data from arrays to other data types

to_csv

Generates CSV line from an array. This handles escaping. Nil values and empty strings will also be expressed within the csv line.

Syntax

Input.to_csv

  • Input - An input of list datatype.

Sample usage

Formula

Result

["John Smith", "No-Email", " ", nil, "555-1212"].to_csv

"John Smith,No-Email, ,,555-1212"

["John Smith", "No-Email", " ", nil, 1212].to_csv

"John Smith,No-Email, ,,1212"


to_json

Converts hash or array to JSON string.

Syntax

Input.to_json

  • Input - An input datapill. It can be a list or hash datatype.

Sample usage

Formula

Result

{"pet" => "cat", "color" => "gray"}.to_json

{"pet":"cat","color":"gray"}

["1","2","3"].to_json

["1", "2", "3"]


to_xml

Converts hash or array into XML string.

Syntax

Input.to_xml

  • Input - An input datapill. It can be a list or hash datatype.

Sample usage

Formula

Result

{"name" => "Ken"}.to_xml(root: "user")

<user><name>Ken</name></user>

[{"name" => "Ken"}].to_xml(root: "users")

<users><user><name>Ken</name></user></users>


from_xml

Converts XML string to hash.

Syntax

Input.from_xml

  • Input - Input XML data.

Sample usage

Converting XML string to hash


encode_www_form

Join hash into url-encoded string of parameters.

Syntax

Input.encode_www_form

  • Input - An input of hash datatype.

Sample usage

Formula

Result

{"apple" => "red green", "2" => "3"}.encode_www_form

"apple=red+green&2=3"


to_param

Returns a string representation for use as a URL query string.

Syntax

Input.to_param

  • Input - An input of hash datatype.

Sample usage

Formula

Result

{name: 'Jake', age: '22'}.to_param

"name=Jake&age=22"


keys

Returns an array of keys from the input hash.

Syntax

Input.keys

  • Input - An input of hash datatype.

Sample usage

Formula

Result

{"name" => 'Jake', "age" => '22'}.keys

["name", "age"]

 

Other formulas

This section covers formulas that work with a number of data types.

null

Gives a null/nil value. Note: passing this into an input field will not update the field value as null. Use clear formula to update a field value to null. Remember to toggle the field to formula mode.

23e1ff94-0c72-46e5-a93f-124edebcf45b.png

clear

Clears the value of the field in the target app to null/nil. Remember to toggle the field to formula mode.

Use clear formula instead of null when looking to clear field in target app

0e23ca18-5bb6-4ea9-a234-84d2494eecb5.png

uuid

Generates an UUID.

Example

Example

Result

uuid

"c52d735a-aee4-4d44-ba1e-bcfa3734f553"


encrypt

Encrypts the input string with a secret key using AES-256-CBC algorithm. Encrypted output string is packed in RNCryptor V3 (opens new window)format and base64 encoded.

Note: The encryption key should not be hard coded in the recipe. Use account properties (with key or password in the name) to store the encryption keys.

Example

encrypt([ssn], [encryption_key])


decrypt

Decrypts the encrypted input string with a secret key using AES-256-CBC algorithm. Encrypted input string should be packed in RNCryptor V3 (opens new window)format and base64 encoded.

Note: The encryption key should not be hard coded in the recipe. Use account properties (with key or password in the name) to store the encryption keys.

Example

decrypt([encrypted_ssn], [encryption_key])


encode_sha256

Encodes a string or binary array using SHA256 algorithm

Example

"hello".encode_sha256


encode_hex

Converts binary string to its hex representation

Example

Example

Result

"0101010101011010".encode_hex

"30313031303130313031303131303130"


decode_hex

Decode hexadecimal into binary string

Example

Example

Result

"30313031303130313031303131303130".decode_hex

"0101010101011010"


encode_base64

Encode using Base64 algorithm

Example

Example

Result

"Hello World!".encode_base64

"aGVsbG8gd29ybGQh"


decode_base64

Decode using Base64 algorithm

Example

Example

Result

"aGVsbG8gd29ybGQh".decode_base64

"Hello World!"


encode_url

URL encode a string

Example

Example

Result

"Hello World".encode_url

"Hello%20World"


encode_urlsafe_base64

Encode using urlsafe modification of Base64 algorithm

Example

Example

Result

"Hello World".encode_urlsafe_base64

"SGVsbG8gV29ybGQ="


decode_urlsafe_base64

Decode using urlsafe modification of Base64 algorithm

Example

Example

Result

"SGVsbG8gV29ybGQ".decode_urlsafe_base64

"Hello World"


as_string

Decode byte sequence as string in given encoding

Example

Example

Result

"SGVsbG8gV29ybGQ=".decode_base64.as_string('utf-8')

"Hello World"


as_utf8

Decode byte sequence as UTF-8 string

Example

Example

Result

"SGVsbG8gV29ybGQ=".decode_base64.as_utf8

"Hello World"


to_hex

Converts binary string to its hex representation

Example

Example

Result

"SGVsbG8gV29ybGQ=".decode_base64.to_hex

"48656c6c6f20576f726c64"


SHA1

Encrypts a given string using the SHA1 encryption algorithm. Details here(opens new window)

Example

Example

Result

"abcdef".sha1.encode_base64

"H4rBDyPFtbwRZ72oS4M+XAV6d9I="


HMAC formulae

Creates a HMAC signatures with a variety of signing algorithms

Example

Signing algorithm

Example

SHA-256

"username:password:nonce".hmac_sha256("key")

SHA-1

"username:password:nonce".hmac_sha1("key")

SHA-512

"username:password:nonce".hmac_sha512("key")

MD5

"username:password:nonce".hmac_md5("key")


md5_hexdigest

Accepts a string and creates message digest using the MD5 Message-Digest Algorithm

Example

Example

Result

"hello".md5_hexdigest

"5d41402abc4b2a76b9719d911017c592"


jwt_encode_rs256

Creates JWT with RS256 - RSA using SHA-256 hash algorithm

Example

Example

Result

appconnect.jwt_encode_rs256({ name: "John Doe" }, "PEM key")

"eyJhbGciO..."


parse_yaml

Parse a YAML string. Supports true, false, nil, numbers, strings, arrays, hashes

Example

Example

Result

appconnect.parse_yaml("---\nfoo: bar")

"{ "foo" => "bar" }"

appconnect.parse_yaml("---\n- 1\n- 2\n- 3\n")

"[1, 2, 3]"


render_yaml

Render an object into a YAML string.

Example

Example

Result

appconnect.render_yaml({ "foo" => "bar" })

"---\nfoo: bar\n"

appconnect.render_yaml([1,2,3])

"---\n- 1\n- 2\n- 3\n"


lookup

This formula allows you to lookup values from your AppConnect lookup tables via a key. It is case sensitive and data type sensitive.

If you use a data pill in the lookup formula, it is recommended that the data is converted to the right format. For example, integer-type data pills should be converted to string with a .to_s formula if comparing to a column containing both integers and strings.

Example

For example, let's use the following lookup table with name Department Codes with an ID of 6:

5c4db9d0-5827-482b-9892-3d7e1736f590.png

Example

Result

lookup('Department Codes', 'Department code': 'ACC')['Department']

"Accounting"

lookup('Department Codes', 'Department code': 'SLS')['Department']

"Sales"

lookup('Department Codes', 'Department': 'Marketing')['Department code']

"MKT"

lookup('6', 'Department code': 'ACC')['Department']

"Accounting" #interchangeable lookup table name and ID

lookup('Department Codes', 'Department': 'marketing')['Department code']

nil #case sensitive value for "Marketing"

lookup('Department Codes', 'Department': 'Marketing')['Department Code']

nil #case sensitive value for column name "Department code"


lookup_table

This formula allows you to create a static lookup table and define the keys and values. It is case sensitive and data type sensitive.

Example

Example

Result

{"key1" => "value1", "key2" => "value2", "key3" => "value3"}["key2"]

"value2"

{"High" => "urgent", "Medium" => "mid", "Low" => "normal"}["Low"]

"normal"

{"High" => "urgent", "Medium" => "mid", "Low" => "normal"}["low"]

nil

{"High" => "urgent", "Medium" => "mid", "Low" => "normal"}["normal"]

nil

{1 => "1", 2 => "2", 3 => "3"}[2]

"2"

{1 => "1", 2 => "2", 3 => "3"}[2.0]

nil

{1 => "1", 2 => "2", 3 => "3"}["2"]

nil

 

Complex data types

Up to this point, we have only discussed primitive data types like Strings and Integers. With most APIs, data is represented with more complex structures. These can be broadly classified into JSON Objects and Arrays.

Mapping complex data in formula mode

Benefits

  • Deal with primitive arrays

  • You may not have prior knowledge of schema

  • Too many fields in a single object to map

Example

In the following example, we apply tags to Zendesk tickets for associated Escalations, which (in this example) we are tracking in Insightly as a custom object. For the purpose of demonstration, we will perform this using a custom action. According to Zendesk API documentation (opens new window), tags should be sent as an array of strings. The payload should look like this:

1{2 "ticket": {3 "tags": ["WorkJam", "ProductHour"]4 }5}6

Now, this presents a problem for us, because AppConnect input field mapping exist primary as key/value pairs. This required format is a primitive array of strings. This requires a complex data type (Array of Strings).

To do this, simply toggle the Tags input field to formula mode, and form the required structure. This can be done in a few ways.

First, we can perform a test with a statically defined array of strings. Make sure that the input value observes proper JSON syntax. Invalid values in formula mode will raise design time formula errors.

a85fd084-ef28-4a4c-b098-4330fd702726.png

Next, it is a good idea to perform some tests to make sure that the custom action updates the ticket with the new tags as expected. At this point, you can improve the recipe further to update tickets with tags dynamically.

Since Zendesk API expect an Array of Strings, we need to retrieve only the Escalation Name values from the Escalations returned from a previous action.

We do this by using the pluck formula, which conveniently returns an array of Escalation Name values, perfect!

ab29af2c-e7c4-441e-8684-ee53deb7da92.png

Finally, make sure that the right data is sent by checking the job details. Always make sure to test your work before setting a recipe live!

Was this article helpful?