JavaScriptによるKintone上の値変更検出

Kintoneでの値変更をJavaScriptでどう検知すべきか調査した結果を示した。

編集後の値で処理を施す場合

以下の change.js の作りで、console.log している箇所で newValue を使って処理すれば良い。

※『建物名』列の変更を検知したい場合の例。任意のフィールドコード名に書き換えること。

変更前の値を使いたい場合

変更前の値を使いたい場合は工夫が要る。

オンライン検索すると『event.changes.field.value』で比較が出来るという情報もあったが、嘘だった。『event.changes.field.value』には変更後の値しか入らないので注意して欲しい。

2025年3月9日現在では change のイベントで変更前の値は取得出来ない。ではどうするか。2種類の方式が考えられる。

1.変更前の値を保存しておき変更時に比較

レコードの作成/編集画面を表示した時に変更前の値を oldValue 変数に取得しておき、変更時に利用する方法。

これは無駄な列を追加しない分データ構造を美しく保てるメリットがあるものの、別画面での情報を使うことになるのがコードの独立性上美しくない。

2.変更前の値保存用の列を用意し比較

ユーザーが変更出来ない列『建物名変更前』を設けておき、編集時に値を退避しておく方法。

これは「1」の方法とは対照的で、無駄な列を追加するためデータ構造は汚くなるデメリットがあるが、処理は編集画面のみで完結するためコードの独立性上美しい。

所感

方法「1」も「2」も甲乙つけがたいメリデメがあるが、Kintoneがユーザー部門向けのサービスであることを考えると、分かりやすく御しやすい「2」の方式をオススメする。

ただ、使う側にとって嬉しいのはBefore-Afterの変更前・変更後情報両方を event 変数が持ちイベントの性質上求められ易い措置がとれるKintoneの仕様変更な気がする。処理速度に響きそうなため現実的でないかな。

Kintoneでの複数列組み合わせへの一意性制約実装

Native Kintoneの世界における、プラグインなしJavaScriptで出来る複数列組み合わせの一意性制約実現コードの紹介。

課題

Kintoneでは一つ一つの列に「値の重複を禁止する」設定を施せばそれぞれの列を一意に(ユニークに)出来るが、この設定では複数列組み合わせでの一意性制約は実現出来ない。

例えばアプリに建物とフロア(1階、2階、3階….)の関係性を持たせたい場合。

「建物ID:1234」⇒「フロア:1階」の行や「建物ID:1234」⇒「フロア:2階」や「建物ID:1235」⇒「フロア:1階」の行を一行ずつ載せたく、同じ建物であれば同じフロアを重複登録出来ないようにしたいから、仕組的にどうにかしたいというのがトピックであり、これをプラグインなしで実現したいのが前提条件である。

対策例

1.建物ID、フロア列を持つアプリにID列を設け、「値の重複を禁止する」にチェックを入れておく。

2.レコード作成時/更新時に自動的に建物IDと建物名を結合した値がID列に入るよう、JavaScriptで更新する。具体的には以下コードをupdate_id.jsファイルに保存(UTF-8 BOMなし)する。

3.管理者としてKintoneにログインし、当該アプリの設定画面から「JavaScript / CSSでカスタマイズ」を選択し、PC用にもスマートフォン用にもアップロードして保存する

4.アプリを更新する。

この方式であれば、record.ID.value = … の部分を編集すれば列数が増えても対応出来るし、他の列にも値を入力したければそれ用の処理行を足せば済む。

注意事項

結合に用いる文字

例では _(アンダースコア)の記号を使って建物IDとフロアを結合しているが、仮に建物IDやフロアに _(アンダースコア)を使っていれば一意制約が正常動作しなくなる場合がある。

究極的には結合元の列に使わない記号で結合すれば複数列による一意制約をかけられるため、取り扱うデータに応じて結合に用いる記号は変えること。

JavaScriptで利用する列名

JavaScriptコードで指定するのは、画面表示に用いる「フィールド名」の値ではなく「フィールドコード」に用いる値である

上述の「ID」で言えば、下図の通りフィールドコードの内容が record.ID.value で用いる列名と一致するよう確認すること

Kintoneのコーディングガイドラインへの適合

https://cybozu.dev/ja/kintone/docs/guideline/coding-guideline

Kintoneのコーディングガイドラインに適合した書き方にすること。

適合しない場合、Kintoneの既存機能や将来のアップデート時に不具合が生じ易いのだが、ちまたには本来Kintone開発に不要なライブラリインストールが手順に載っていたり、動作はするもののコーディングガイドラインを無視して例示しているものがあるため本番利用に向けては注意して欲しい。

不安になった場合はCopilotやGeminiなど生成AIにコードを添えて質問。『引用したJavaScriptコードはリンク先URL:https://cybozu.dev/ja/kintone/docs/guideline/coding-guideline/ のコーディングガイドラインに適合していますか。していない場合は適合するよう修正したコードを示してください』のように修正してもらうと良いだろう。

CentOS 8からRocky Linux 9への移行の思い出

CentOS8のサポート終了は2021年12月31日。2025年元旦に再構築・移行を決意し、途中発熱で中断したものの1月12日に対応が完了したため思い出を残す。

1.移行先の選定

サービスは、過去困っていなかったので同じさくらのVPS(v5) 1G IK01のプランを選んだ。

OSはCentOS8の後継としてはAlmaLinuxとRockyLinuxが有力だったが、結果的に選んだのはRockyLinuxである。どちらも甲乙つけがたい素晴らしいOSなため、RockyLinuxが優れていたから選んだということではない。ただ、趣味のサーバーであり、直前にAlmaLinuxを使っていたから今回はRockyLinuxにしようという程度の選定理由である。

AlmaLinux と RockyLinuxの比較参考: https://blog.apar.jp/linux/15640/

2.ホストネットワーキング

ホストネットワーキングとは、Dockerの仮想ネットワークと違うという意味でホストを付けている。特別難しいことはせず、さくらVPSの機能で一部プロトコルのポート開放を行い、公開鍵認証方式のみ許可するようありがちな設定を適用した。

特筆すべき点で言えば、鍵への拘り。さすがに今の時代RSAはなぁということで、ecdsa_nistp521の鍵を使うことにした。

更にiPadで『https://it.sifr.me/study/operate-your-ssh-server-with-buffer-editor/』の設定を適用した。これで、出先でサーバーを操作したいと思った場合はiPadから操作する環境が整った。

2.Docker CEのインストール

CentOSよりひと手間入るという程度で、上のリンク先に従えばすんなり入る。簡単だった。

問題は、過去インストール版との違いで、3点Dockerの違いに悩まされた。

2.1.docker compose

昔は docker 本体とは分けて docker-compose コマンドを使っていたが、最近は統合されたらしい。

docker-compose と書いていた部分を全て docker compose (ハイフン→半スぺ)に変更する。

2.2.docker-compose.yml の services:

docker-compose.yml の最初に services: から始めないと動作しない。具体例としては以下が一目瞭然なのだが、全部のdocker-compose.ymlにこれを足していくのは大変手間だったぞ。

2.3.docker-compose.yml の networks:

docker は初期とネットワークのコンセプトが変わっている。多分セキュリティ確保のため『デフォルトでは他のコンテナ同士で連携させない』ようにしていて、コンテナ間で通信をするにはネットワークを明示してドメイン名解決&通信させるのが◎である。

この違いを考慮していないと『host not found in upstream “$server_name”…』のエラーが出力されることとなる。

※2025年1月時点、Dockerのネットワークの仕様については『Dockerネットワークを理解したい #docker-compose – Qiita』が詳しい

実際の対策としては以下のようにネットワーク設定を設けておき、

docker network create mainnetwork

以下のように docker-compose.yml にネットワーク情報を載せると管理し易い。

3.コンテナの最新化

ここからは個別のコンテナ移行を取り扱う。権限を維持したままデータをコピーしておくのは前提として、引っかかった部分を説明する。

3.1.openldapの延命措置

別記事にまとめた『https://it.sifr.me/study/extending-the-life-of-osixia-openldap-container/』の通り。

osixia/openldapを使い続けるには調査と工夫が必要だった。

3.2.php-fpm

一気に最新版にするぞと PHP8.4にするつもりで php:8.4-fpm-alpine で構築を進めたが、結果的に8.2に落ち着いた。理由は2つある。

一つはpecl imagemagick が8.4で破棄された関数を使っているためコンパイルに失敗するから(参考:https://github.com/Imagick/imagick/issues/689)。

もう一つはNextCloud Version30が8.4に対応しておらず、31から8.4対応となっているから(参考:https://github.com/nextcloud/server/wiki/Releases-and-PHP-versions)である。

3.2.1.Alpine Linuxでの標準ライブラリの変化

昔は phar, iconv をインストールする場合は明示していたが、これらはAlpine Linuxでは標準で入るようになった(外したい場合にコマンドで明示するようになった)。Dockerfileのインストールコマンドからこれらを外す必要がある。

なお、インストール可能な項目を調べたところ以下項目が有効だった。

bcmath, bz2, calendar, ctype, curl, dba, dl_test, dom, enchant, exif, ffi, fileinfo, filter, ftp, gd, gettext, gmp, hash, iconv, intl, json, ldap, mbstring, mysqli, odbc, opcache, pcntl, pdo, pdo_dblib, pdo_firebird, pdo_mysql, pdo_odbc, pdo_pgsql, pdo_sqlite, pgsql, phar, posix, random, readline, reflection, session, shmop, simplexml, snmp, soap, sockets, sodium, spl, standard, sysvmsg, sysvsem, sysvshm, tidy, tokenizer, xml, xmlreader, xmlwriter, xsl, zend_test, zip

3.2.2.メモリ不足

opcache, redis のようにコンパイルに時間のかかるインストールはいつも途中で止まる。原因は見出しの通りメモリ不足。昔は同じプランのさくらVPSでフリーズすることなく一発で出来ていたから、Docker CEのビルドはメモリ使用量が昔より増えてると思った方が良さそうだ。

SWAPで解決できるのでさくらVPSのプランを上げる必要はない。

3.2.3.CLIでの処理の取り扱い変化

昔はPHP-FPMでCLIが使えた。例えばNextCloudでコマンドラインでのアップグレードがしたいのであれば『php occ upgrade』のコマンド実行で済んでいたのだが、現在は『php –define memory_limit=1024M –define apc.enable_cli=1 occ upgrade』とメモリ不足対策やAPCuの設定を入力しないと動作しない。実際に昔のアップグレードコマンドを実行すると以下の通りエラーとなる。

Copilot先生に聞いたところでは、PHPは通常のPHP処理とCLIで設定を分けるようになった。そしてPHP-FPMはCLIで使うタイプのものではないようで、PHP-FPMにapc.enable_cli=1の設定を入れると起動が出来ない。なのでCLIで実行したい時は都度パラメータを渡してほしいということだった。

Copilotが嘘を言っているんじゃないかとか、ちょっと違和感感じてしまうところだけれど動けば良い派だからよしとする。

3.3.nginx proxy <-> letsencrypt の仕様変更

皆大好きな nginx proxy とLet’s Encryptで自動的に連携出来るミドルウェア構築の強い味方コンボだが、BASIC認証を含むサイトを設置すると、nginx proxy が立ち上がらないことに気づいた。

https://github.com/jwilder/docker-letsencrypt-nginx-proxy-companion

どうやら、BASIC認証がかかっている場合は直接アクセスが出来ないため『自分が所有者です本物です』という証が要るようで、ログを見ると『/.well-known/acme-challenge/』配下のURLへアクセスが来るのが分かる。

以下のように当該URL配下へのアクセスをBASIC認証対象外にしておけばnginx proxy が落ちるのは回避出来た。

3.4.NextCloud

地味に困ったのが、『NextCloudアップグレード途中、工程5の間にメモリ不足エラーになってしまい止まってしまった』件である。メモリ不足エラーは『php –define memory_limit=1024M –define apc.enable_cli=1 occ upgrade』の1024Mのようにメモリ指定をして実行すれば解決できるのだが、途中まで進めてしまった状況は再度アップグレードコマンドを実行しても『Step 5 is currently in process. Please call this command later.』と応答が来るだけで解決出来ない。

3.4.1.Step 5の途中扱いをリセットして再試行

ステップを中断した場合は、前のステップが終わったところまで戻せば進められる。

具体的には <NEXTCLOUD_ROOT>/updater-ocflfrurabky/.step を編集し、{“state”:“start”,“step”:5} の記載を {“state”:“end”,“step”:4} に書き換えてから『php –define memory_limit=1024M –define apc.enable_cli=1 occ upgrade』を再実行すれば良い。以下URLが参考となる。

https://help.nextcloud.com/t/stuck-on-update-process-step-5-is-currently-in-process-please-reload-this-page-later/58371/8

3.4.2.既に最新版と言われる

明らかに最新版でないのに、『php –define memory_limit=1024M –define apc.enable_cli=1 occ upgrade』を実行すると既に最新版と言われる可能性がある。

これは何をしたくてこの表現にしたのか理解に苦しむが、実態としては『アップグレード準備が完了しましたわ』な状態で、アップグレードの適用まで至っていない状態。

以下コマンドで適用すると、次のメジャーバージョンアップグレードの処理を進められる。

↓ 調査に役立ったURL

https://help.nextcloud.com/t/nextcloud-is-already-the-latest-version/156063

結果的にアップグレードに使うと◎なコマンドを載せておく。