コネクター構築: トリガーの構築
トリガーの構築は、アクションとほぼ同じ形式に従います。 オブジェクトベースにするには、先ほど定義したスキーマメソッドに加えて設定フィールドを使用します。 以下では、ポーリングトリガーの例について説明します。 ポーリングトリガー、動的Webhookトリガー、静的Webhookトリガーを作成する際に想定されるブロックには、いくつかの違いがある点に注意してください。
設定フィールドの定義
オブジェクトベースのトリガーを扱う場合、まず設定フィールドと呼ばれるものを定義する必要があります。 設定フィールドは、回答によって他の入力フィールドを動的に生成できるように定義できる特別な入力フィールドです。 トリガーでは追加の入力フィールドが必要になることはあまりないため、この設定フィールドは、このトリガーの想定される出力を動的に生成するために使用されます。
config_fields: [
{
name: 'object',
optional: false,
label: 'Object type',
control_type: 'select',
pick_list: 'object_list_new_updated_trigger',
hint: 'Select the object type from picklist.'
}
],
invoiceを選択すると、invoice関連のデータピルが表示されます
ここでは、サポート対象として追加のオブジェクトを導入するときに簡単に追加できるピックリストも紹介します。
動的入力フィールド
設定フィールドを使用して、ユーザーの選択に基づいて入力フィールドを動的に生成することもできます。 選択されたオブジェクトで、正確な入力フィールドを表示する前に追加情報が必要なシナリオについては、入力フィールドの定義セクションを参照してください。
タイトル、サブタイトル、説明、ヘルプテキストの定義
また、アクションに役立つタイトルと説明を定義することを強くお勧めします。これは非常に重要です。 オブジェクトベースのアクションを扱う場合、これはコネクターを使用するレシピの読みやすさを高めるだけでなく、コネクターでレシピを構築するユーザーのユーザーエクスペリエンスを向上させるのに役立ちます。
triggers: {
new_updated_object: {
title: "新規/更新されたオブジェクト",
subtitle: "オブジェクトが作成または更新されたときにトリガーされます",
description: lambda do |input, picklist_label|
"新規/更新された<span class='provider'>" \
"#{picklist_label['object'] || 'オブジェクト'}</span>(" \
"<span class='provider'>XYZ Accounting</span>)"
end,
help: lambda do |input, picklist_label|
{
body:
"XYZで#{picklist_label['object'] || 'オブジェクト'}が作成" \
'または更新されたときにトリガーされます。'
}
end,
config_fields: [
{
name: 'object',
optional: false,
label: 'オブジェクトタイプ',
control_type: 'select',
pick_list: 'object_list_new_updated_trigger',
hint: 'ピックリストからオブジェクトタイプを選択します。'
}
],
}
}ここでは、コネクター内のさまざまなアクションの中からユーザーがそのアクションを把握できるように、タイトルとサブタイトルを定義します。 タイトルは簡潔に保ちつつ、サブタイトルを使用してもう少し詳しい情報を提供することを忘れないでください。
説明では、ユーザーがconfig_fieldで選択したときにアクションの説明を動的に変更するために、lambda関数(上記の例を参照)を使用できます。 上記の例に示すように、ヘルプテキストでも同じことができます。
動的な説明がない悪い例
動的な説明がある良い例
入力フィールドの定義
トリガーではユーザーからの設定があまり必要ないため、ここでの例ではオブジェクト定義を呼び出す必要はありません。 トリガーで可能な限り推奨するパターンの1つは、トリガーを初めて開始したときにユーザーが過去にさかのぼってデータを取得できるように、オプションの入力フィールドを追加することです。 この入力フィールドはタイムスタンプ値を受け取り、それを使用してデータを取得します。
入力
input_fields: lambda do
[
{
name: 'since',
label: 'When first started, this recipe should pick up events from',
type: 'timestamp',
optional: true,
hint: 'When you start recipe for the first time, it picks up Salesforce records ' \
'from this specified date and time. Once recipe has been run or tested, ' \
'value cannot be changed.'
}
]
end,pollブロックの定義
ポーリングトリガーでは、pollブロックが各ポーリングのコードを実行する場所です。 pollブロックでは、前回のポーリングからの任意のデータを参照できるclosure引数など、さまざまな引数を使用できます。 このclosure値は、トリガーが最後にポーリングした場所に関するカーソルを保存できるようにするため、便利です。 多くの場合、closureには最後に確認したレコードのタイムスタンプ値と、即時にポーリングする必要がある場合のオフセットが保存されます。
ポーリングトリガーのベストプラクティス
ポーリングトリガーを構築する場合、レコードのリストを返し、タイムスタンプによるレコードのフィルタリング用クエリパラメーターをサポートするエンドポイントを使用するのが最適です。 例として、GreenhouseのGet list candidates APIドキュメントを参照してください。
XYZ Accountingからの想定されるJSONレスポンス
{
"results": [
{
"TxnDate": "2019-09-19",
"ID": "1",
"TotalAmt": 362.07,
"Line": [
{
"Description": "Rock Fountain",
"SalesItemLineDetail": {
"Qty": 1,
"UnitPrice": 275,
},
"Line-Num": 1,
"Amount": 275.0,
"Id": "1"
},
{
"Description": "Fountain Pump",
"SalesItemLineDetail": {
"Qty": 1,
"UnitPrice": 12.75,
},
"LineNum": 2,
"Amount": 12.75,
"Id": "2"
}
],
"DueDate": "2019-10-19",
"DocNumber": "1037",
"Deposit": 0,
"Balance": 362.07,
"CustomerRef": {
"name": "Sonnenschein Family Store",
"value": "24"
},
"BillEmail": {
"Address": "[email protected]"
},
"BillAddr": {
"Line1": "Russ Sonnenschein",
"Long": "-122.1141681",
"Lat": "37.4238562",
"Id": "95"
},
"MetaData": {
"CreateTime": "2014-09-19T13:16:17-07:00",
"LastUpdatedTime": "2014-09-19T13:16:17-07:00"
}
},
// more results
],
"more_results": true
}pollブロック
poll: lambda do |connection, input, closure|
limit = 100
closure = closure || {}
updated_since = (closure['last_updated_since'] || input['since']).to_time.utc.iso8601
params = {
"order_by" => "updated_at",
"order_type" => "asc",
"limit" => limit,
"offset" => closure['offset'],
"updated_since" => updated_since
}
response = call("trigger_#{input['object']}_poll", params)
records = response['results']
poll_again = response['more_results']
if poll_again # If we can poll for more, update offset
closure['offset'] = closure['offset'] + limit
else # If not, reset offset and last_updated_since
closure['offset'] = 0
closure['last_updated_since'] = records.last['MetaData']['LastUpdatedTime']
end
{
events: records,
next_poll: closure,
can_poll_more: poll_again
}
end,pollブロックでは、まず適切なパラメーターでペイロードを準備し、最後にポーリングした時刻より後のレコードのみをクエリします。 これは、前回のポーリングのclosure値を参照して行います。
パラメーターはオブジェクト固有のメソッドに渡されてポーリングを実行し、レスポンスは上記のJSONレスポンスであることが想定されます。 closure値はポーリングのレスポンスに基づいてリセットされ、各pollブロックの出力は、レコード、closureハッシュ、およびトリガーが再度ポーリングすべきかどうかを判定するブール値である"can_poll_more"という、3つの想定値を持つハッシュになります。
詳細については、ポーリングトリガーを参照してください。
dedupブロックの定義
pollブロックから渡されたレコードの配列内の各レコードについて、Workatoはそのレコードを以前に確認したことがあるかどうかもチェックします。 これを行うには、dedupブロックにレコードのさまざまな部分を組み合わせた文字列を含め、一意であることを確保する必要があります。 以下の例では、invoice IDとinvoiceの最終更新タイムスタンプを使用して、この更新されたレコードが以前に確認されているかどうかを判定しています。
dedup: lambda do |record|
"#{record['results']['Id']}@#{record['results']['MetaData']['LastUpdatedTime']}"
end,出力フィールドの定義
出力フィールドは、先ほど使用したものと同じスキーマメソッドを使用して定義できます。 スキーマメソッドを呼び出す際は、レスポンスで想定されるフィールドを返す必要があることをメソッドが認識できるように、パラメーターoutputを渡すことを忘れないでください。 多くの場合、これにはcreated_atやupdated_atタイムスタンプなど、ユーザーが変更できないオブジェクトに関するメタデータが含まれます。
出力
output_fields: lambda do |object_definitions, connection, config_fields|
object = config_fields['object']
input_schema = object_definitions[object]
end,オブジェクト定義
invoice: {
fields: lambda do |connection, config_fields, object_definitions|
# same schema as above
end
},サンプル出力の定義
サンプル出力は、ユーザーが後続のアクションでマッピングしているデータピルに関するコンテキストを示すための優れた方法です。 ラベルだけではまだ混乱の余地がある場合、サンプル出力により、ユーザー自身のアプリケーションからリアルタイムでデータを取得できるため、理解のギャップを埋めることができます。 以下の例では、検索オブジェクトメソッドを使用してユーザー自身のXYZ Accountingインスタンスで見つかった最初のレコードを取得する前に、ペイロードを人工的に構築します。
サンプル出力
sample_output: lambda do |connection, input|
payload = {
"limit" => 1
}
call("search_#{input['object']}_execute", payload)
endこのブロックの出力は、その後、出力フィールドブロックに渡され、一致する各データピルの右側にレンダリングされます。 これにより、ユーザーがトラブルシューティングにかける時間を大幅に短縮できます。
サンプル出力は、各データピルの横にグレーのテキストでレンダリングされます
一般的なコードパターンと制限事項
オブジェクトベースのアクションとトリガーを構築する方法の例をいくつか確認したので、次にコネクターで再利用できるコードパターンについて説明します。
Last updated: