kintaco編集部です。自社のレコード差分プラグインにあるcanonical処理を題材に、kintoneの値を「そのままJSON化して比較する」と起きる問題を整理します。
この記事では、文字列・チェックボックス・ユーザー選択の3種類だけを比較します。画面への着色、基準値の取得タイミング、テーブル行IDの追跡は含みません。製品版にある数値・日時・添付ファイル等の正規化も省いています。
同じ意味なら同じ比較キーにする
文字列では改行コードを揃えます。チェックボックスは選択順を無視します。ユーザー選択は表示名ではなくcodeを比べます。比較用の文字列を返し、実際のレコード値は書き換えません。
const SET_TYPES = new Set(['CHECK_BOX', 'USER_SELECT']);
function canonical(field) {
if (!field || !['MULTI_LINE_TEXT', ...SET_TYPES].includes(field.type)) {
throw new Error('このサンプルの比較対象外です。');
}
const value = field.value;
if (SET_TYPES.has(field.type)) {
if (!Array.isArray(value)) throw new Error('配列を指定してください。');
return JSON.stringify([...new Set(value.map(item => {
if (field.type === 'USER_SELECT') {
if (!item || typeof item.code !== 'string') throw new Error('codeが必要です。');
return item.code;
}
return String(item);
}))].sort());
}
return String(value ?? '').replace(/\r\n?/g, '\n');
}
function changed(before, after) {
if (!before || !after || before.type !== after.type) {
throw new Error('同じ型のフィールドを比較してください。');
}
return canonical(before) !== canonical(after);
}
選択順を無視するなら、コピーしてから並べ替える
チェックボックスの配列をそのままsortすると、比較のために元データを変更してしまいます。サンプルではSetで重複を取り除き、別配列へ展開してから並べ替えます。チェックボックスに順序の意味を持たせる業務には適用しないでください。
ユーザー選択も同じ考え方で、codeを比較キーにします。表示名だけが変わっても、同じユーザーコードなら差分にしません。オブジェクト全体のJSON.stringifyでは、この区別ができません。
基準値は参照のまま保持しない
比較前に、基準となる値を複製しておく必要があります。基準と現在値が同じオブジェクトを指していると、編集後の値が両方へ反映され、差分が消えてしまいます。今回のサンプルの値はJSON互換なので、次の形で複製できます。
const baseline = JSON.parse(JSON.stringify(record));
ただし「いつ基準を固定するか」は別の設計問題です。編集画面表示直後に自動補正が走る場合や、別プラグインの初期設定がある場合には、表示直後と入力開始前で値が異なることがあります。製品版は入力開始前の表示値を基準にし、入力開始後の自動変更も差分に含めます。
サンプルの確認例
console.log(changed(
{type: 'CHECK_BOX', value: ['外観', '異音']},
{type: 'CHECK_BOX', value: ['異音', '外観']}
)); // false
改行差、選択順、ユーザー表示名、コード変更、型の不一致をNode.jsで確認しました。kintoneの実画面でのテストは含みません。基準値の取得、変更イベントとの接続、権限で取得できない項目を扱う処理は、組み込み先で別途必要です。
「違わない」と「比較できない」を分ける
このサンプルは型が違う・対象フィールドがない場合をエラーにします。判定不能をfalseにすると、値が変わっていないと誤解されるためです。一方、製品版の処理では比較対象外の項目をスキップするなど、フォーム全体を扱うための設計があります。そのまま置き換えるコードではありません。
保存前の確認画面として使いたい場合
自社のレコード差分プラグインの仕様・設定画面で、設定から利用する方法も紹介しています。サンプルと製品版の対応範囲は異なります。
無料利用では、非契約ドメインのPC・モバイル一覧画面に有償プランの案内バナーが30%の確率で表示されます。契約済みドメインでは表示されません。一度閉じると、同じブラウザー・同じkintoneドメインでは、全Kintacoプラグイン共通で24時間非表示になります。
参考資料
製品仕様と実コードの確認元:RecordDiff/src/js/core.js(1.0.2)。