一覧へ戻る
ITSM

ServiceNow における current と previous オブジェクトの理解と活用

ServiceNow のサーバーサイドスクリプト、特に Business Rule(ビジネスルール)の中において、currentprevious はデータベース操作の「前後」の状態を保持する非常に重要な GlideRecord オブジェクトです。これらを正しく使い分けることで、レコードの変更検知や精密な条件分岐を正確に行うことができます。

1. current と previous とは?

これらは Business Rule の実行時に ServiceNow システムによって自動的に提供される特別なオブジェクトです。

  • current オブジェクト: 現在処理されているレコードの**「最新の状態(新しい値)」**を指します。
    • すべての同期 Business Rule(before, after, insert, update, delete)でいつでも使用可能です。
    • ユーザーが変更・入力したばかりの最も新しいフィールド値を保持しています。
  • previous オブジェクト: 現在の操作が行われる前の**「元の状態(古い値)」**を指します。
    • データベースの更新時点でシステムが自動生成するスナップショット(Snapshot)であり、トランザクション前の状態を保持するための読み取り専用(Read-only)のオブジェクトです。
    • **更新(update)および削除(delete)**操作の際のみ利用可能です。
    • ⚠️ 注意: 挿入(insert)や非同期(async)型 Business Rule では利用できない(null または空になる)点に注意が必要です。

2. 具体的な違いと特徴

レコードの状態変化を比較する際に、これら2つのオブジェクトの対比が役立ちます。それぞれの仕様の違いは以下の通りです。

✅ current オブジェクトの特徴

  • データの内容: ユーザーが入力したばかりの「更新後(または新規)」の最新値
  • 主な利用シーン: 最新値の取得や条件判定、データベースへ保存する値の操作
  • 状態の一例: ステータスを「進行中」に切り替えた直後の場合、current.state には「進行中」が入ります

✅ previous オブジェクトの特徴

  • データの内容: データベース更新前にシステムが自動取得した、更新前(オリジナル)のスナップショット値
  • 主な利用シーン: 変更前の値との差分比較、監査ログの記録(※読み取り専用のため、この値自体は変更不可)
  • 状態の一例: ステータスを「進行中」に切り替えた場合でも、previous.state には変更前の状態である「新規」等が入ります

3. なぜ使うべきなのか?(実装のメリット)

  • 正確な変更検知: 「ステータスが変わった時のみ」など、特定のピンポイントな変化をトリガーにする高度なロジックが書けるようになります。
  • データ整合性の維持: 変更前の値を参照して監視ログを残したり、不正な変更を意図的に元の値に戻したりすることが容易になります。

4. 主な活用シーンと実装例

✅ 状態変化に応じたスクリプト実行 インシデントのステータスが「In Progress(進行中)」に変わった瞬間だけ通知イベントを発行したいケースなど、currentprevious を比較します。

// 【重要】ステータスが 'In Progress' に変更され、かつ変更前が 'In Progress' ではなかった場合のみ
if (current.state == 'In Progress' && previous.state != 'In Progress') {
    // 特定のイベントをキューに追加
    gs.eventQueue('incident.state.changed_to_in_progress', current, previous.state, current.state);
    
    // システムログにビフォーアフターを記録
    gs.info("ステータスが変更されました。 旧: " + previous.state + " -> 新: " + current.state);
}

⚠️ 注意点:previous が空になるケース(トラブルシューティング)

開発中によく遭遇する「previous が null になってエラーが出る」という問題は、主に以下の原因で発生します。これらを理解しておくことがバグ回避の近道です。

  • 新規作成(insert)時: 新しく作られるレコードには「以前の状態」が存在しないため、previous スナップショットは生成されません。
  • 非同期(async)BR: パフォーマンス最適化の仕様として、非同期処理には previous オブジェクトのコピーが渡されない(破棄される)仕様になっています。

💡 補足:よりスマートな判定方法(changesTo)

上記の実装例のように !=== を使って直接比較する以外にも、ServiceNow 独自の組み込みメソッドを活用するとコードをより完結に読解しやすく書くことができます。

  • current.<field>.changesTo(value) メソッド: 指定したフィールドの値が「特定の値に変更された直後か」をこれひとつで判定してくれます。(例: current.state.changesTo('In Progress')
  • Condition Builder(条件ビルダー)の活用: そもそもスクリプト内に if 文を書く前に、Business Rule の「Condition」設定欄で [State] [changes to] [In Progress] のように設定する方が、システムパフォーマンスの観点で最適です。

まとめ

  • スクリプトにおける current は「今の姿」、previous は変更前の「スナップショット(読み取り専用)」です
  • データの変更をトリガーにする場合は、必ずこの2つを比較して「差分」をチェックしましょう
  • insert や async では previous が使えない という制限を常に意識して開発しましょう

一言まとめ: 👉 値のビフォーアフターを制御したいなら、current と previous (または changesTo) の組み合わせをマスターしよう!