この記事は以下の記事の続編です。
ServiceNowでレコードを参照するときのデータ型を意識する (2)
https://qiita.com/yujiarakitokyo/items/adc0e5644ebff5636ee9
はじめに
ServiceNowの実装で、スクリプトから何気なくテーブル上の値を取得しているけれど、それって厳密には何を見ているんだっけという疑問から始まったシリーズ第3回目です。
前回はかなり闇の深い話になってしまいましたが、今回はあっさりした内容です。結論としては、GlideQuery
は型の扱いという観点ではとても扱いやすくて便利ですよという話になります。なのでさっさと始めましょう。
ケース
前回の続きということで、こちらのサンプル画面をベースに考えます。
この画面上に作られたサンプル選択肢(sample_choice
)とかサンプル数値(sample_integer
)とかサンプル真偽値(sample_boolean
)の値を取得して、そのデータ型がどうなっているのかを見ていきたいと思います。
検証
選択肢フィールド
まずは選択肢フィールドから。前回との違いは、GlideRecord
の代わりにGlideQuery
を使うことです。最初はとっつきにくいと思うかも知れませんが、慣れるとBuilderパターンのおかげで書くテンポ感が良いので、GlideRecord
には戻れなくなること請け合いです。1
(function() {
new global.GlideQuery('x_snc_qiita_sample_qiita_task')
.where('number', 'QTASK0001001')
.selectOne('sample_boolean', 'sample_choice', 'sample_integer')
.ifPresent((e) => {
gs.info(`Test1-1 Value of sample_choice: ${e.sample_choice}`);
gs.info(`Test1-2 Type of sample_choice: ${typeof e.sample_choice}`);
gs.info(`Test1-3 sample_choice equals to: ${e.sample_choice === '1'}`);
});
})();
GlideQuery
そのものの解説はまた別に書きたいので、掘り下げはしませんが、簡単なポイントは以下にまとめておきます。
ポイント
- 1件だけ取得したい場合は、
selectOne
メソッドを使う。同メソッドの引数に渡したフィールドおよびシステムIDを取得します。(GlideRecord
と違って指定したフィールドだけが返されます) - クエリが成功するか否かに依らず、
Optional
のオブジェクトが返される。 -
Optional
のifPresent
メソッドを使うと、クエリが成功してOptional
に値があるときはメソッドの引数に渡したコールバック関数を実行し、逆に値が取れていないときは何もしない2。 - コールバック関数に対して引数から渡されるのは1レコード分のデータで、今回の場合、
selectOne
の引数に渡した3つのフィールドとシステムID、ここでは合計4フィールドの値を持ったオブジェクトが渡されます。なので、そこからドットを挟んでフィールド名を与えると、フィールドの値が取得できます。
結果は以下の通り。
上のプログラムでe.sample_choice
という記述で取り出した値はそのまんま、文字列リテラルの「1」でした。機能は豊富なものの直感的ではなかったGlideElement
みたいな中間的なオブジェクトを介さないので、そのまま'1'
と厳密に比較しても構いません。
数値フィールド
数値はこちらのコードで試してみましょう。
(function() {
new global.GlideQuery('x_snc_qiita_sample_qiita_task')
.where('number', 'QTASK0001001')
.selectOne('sample_boolean', 'sample_choice', 'sample_integer')
.ifPresent((e) => {
gs.info(`Test2-1 Value of sample_integer: ${e.sample_integer}`);
gs.info(`Test2-2 Type of sample_integer: ${typeof e.sample_integer}`);
gs.info(`Test2-3 sample_integer equals to 42: ${e.sample_integer === 42}`);
});
})();
こちらも結果はこの通り。そのまま過ぎて何も面白くありませんが、数字を数字として扱えるのは事後の処理を考えると大きなメリットがあります。
True/Falseフィールド
真偽値(True/False)も同じです。
(function() {
new global.GlideQuery('x_snc_qiita_sample_qiita_task')
.where('number', 'QTASK0001001')
.selectOne('sample_boolean', 'sample_choice', 'sample_integer')
.ifPresent((e) => {
gs.info(`Test3-1 Value of sample_boolean: ${e.sample_boolean}`);
gs.info(`Test3-2 Type of sample_boolean: ${typeof e.sample_boolean}`);
});
})();
結果はこの通り。真偽値が真偽値として取得できるのは、前回の挙動と比べると格段のシンプルさであることがわかります。
まとめ
今回は、GlideRecord
ではなく、GlideQuery
を使ってクエリを投げたときの結果の型について調べてみました。GlideRecord
の各フィールドはGlideElement
で取得できたのと異なり、GlideQuery
を使うとシンプルにプリミティブ型で値を返してくるので、その後の処理の見通しが良いです。
これが便利さの全てではなく他にも面白い機能がたくさんあります。完全にGlideRecord
を置き換えるかというと、そうでもない3のですが、コールバック関数を多用する仕組みは、Tokyoから使えるようになったECMAScript 2021(ES12)のラムダ式との相性が抜群ですので、ぜひ活用してみたいものです。
-
もちろん、現場ではある程度の開発標準は設けるべきですし、メンバーのスキルによっては使わない方向で決めておいた方がいいこともあるかも知れません。しかし、クエリ結果の型の扱いを厳密にしやすいこと、
GlideQuery
からの戻り値を扱うためのStream
クラスとOptional
クラスのメソッドに便利なものが多くて事後処理を書きやすいことなどから、生産性は高いと思います。 ↩ -
惜しいのが、ServiceNowにはJavaのStream APIのような
ifPresentOrElse
メソッドがないことで、このため、値がないときに何かをしたくてもうまく書くことができず、結局値を取り出して回りくどい処理を書く必要があります。 ↩ -
例えば、ビジネスルールの組み込みグローバル変数
current
とprevious
はGlideRecord
なので、否応なしに使うことになります。 ↩