FileMaker でメディアデータベースを作る話の一環、レコードとメディアを複製する機能、その名もバージョンについての考察です。
FileMakerで画像や動画などメディアを管理するデータベースを作っていて、1レコードに1メディアを登録する運営をしている前提です。このデータベース内でレコードとメディアを複製する機能について考えます。ここでは複製されたレコードとメディアをバージョンと呼ぶことにします。
バージョンの必要性と意味
オリジナルに手を付けず複製品を弄る
メディア管理を作っていく初期段階ではレコードの複製が必要になることはほとんどありません。それが必要となるのはメディアに変更を加える機能が搭載された後です。変更を加えるわけですからオリジナルには手を付けず、複製してそっちを弄くるという安全な措置が求められます。複製の必要性はここから発生しました。
「作り方」シリーズで実作しているメディア管理ファイルでは、ExifTool の使用によりファイルのメタデータを編集できる機能を手に入れました。メタデータだけであってもファイルを変更することには違いありません。「変更する前に必ずバックアップしましょう」を別の意味で実現するのが、複製を作ってそっちを触ることです。
オリジナルとの関係性を保った複製品
複製したときに「どのレコードを複製したのか」の情報を保持することが必要と考えました。特定レコードの単なる複製をわざわざバージョンと名付けた意味はここにあります。元レコードとその複製レコードの関係を保ちます。別の言い方では親子関係です。元レコードを親、バージョンを子とする関係にあたります。
バージョンの定義
バージョンとはなんぞや。その定義は「親子関係を維持した複製」です。もっと複雑な仕組みも考えましたが開発上の混乱必至なのでやめたんです。最もシンプルなことが最適解の筈です。
定義上、次のような制約を設けました。
- 元となるレコードはバージョン(子)をいくつでも作ることができる
- バージョン(子)はバージョン(子の子)を作ることはできない
- バージョンは必ず格納で保存される
あるレコードが親であったり子であったりする混乱を防ぐため、バージョンのバージョンを作れなくしました。
最後の「必ず格納」これだけが悩ましいところでした。格納用フォルダを用意してそこにメディアファイルを複製し参照するほうがスクリプト作成など技術上簡単で有利だからです。しかし簡単で有利なことが災いを生むこともあるので、敢えて手順がややこしくなる格納を選びました。
格納(挿入)で登録の罠
バージョンは必ず格納で保存しますが、FileMakerでオブジェクトを格納(挿入)管理するといろいろな罠が待ち受けています。
<変更されています>
まず、格納したファイルを変更すると厄介なことになります。少しでもファイルを変更するとオブジェクトは<変更されています>表記となり管理できなくなります。こうなってしまえばFileMakerの機能では書き出すこともできませんしどうにもなりません。外部コマンドラインツールで直接ファイルを操作して解決する以外なくなります。
ファイル拡張子の変更
格納ファイルはファイル名や拡張子が変更されることがあります。例えば拡張子が「.jpeg」のファイルを格納すると「.jpg」になります。元のパスを元にバージョンのパスを計算で作ると問題が生じます。必ず GetAsText で取得し確認する必要があります。
ファイル名の変更
ファイル名に連番が付くことがあります。書き出してから挿入したり、<変更されています>を再挿入したり、同じ名前のファイルを上書きしようと重ねて挿入したりすると「_1」「_2」あるは「_1_1_1」みたいに連番的なテキストが入ります。一旦連番が入ると直接外部からファイル操作をしないと消えません。この件で具合が悪いのは、FileMakerの管理上は連番をないものとして扱っていることです。GetContainerAttribute でファイル名をゲットすると「○○.jpeg」のままなのに、GetAsText でパスを取得すると「○○_1.jpg」になります。
これらの罠は即ち「格納ファイルを変更するな」のFileMakerからのメッセージでもあります。そもそもバージョンはファイルを変更・編集するための措置だったのに変更不可では意味ありません。
バージョン作成
さてそんなわけでバージョンとは「元レコードの情報を保持した複製」ですので、メインテーブルにフィールドが一つ必要になります。それは parent です。
parent
メインテーブルには「ID」フィールドがあります。新たに作成するフィールドは「parent_id」としました。複製したら、複製元のIDをparant_idに転記します。はい。これで親子関係が成立しました。
親子をより判りやすく、テーブルオカレンスでメインテーブルを複製し「親」と「子」を作ります。メインテーブルのIDとparent_idを繋げたものが子、メインテーブルのparent_idとIDを繋げたものが親です。
これを元にバージョンを技術的に定義するとこうなります。
- parent_id が空ならバージョンではない
- parent_id が空でなければバージョンである
- parent_id 内容が複製元のIDである
- 子parent_id が空なら親ではない
- 子parent_id が空でなければ親である
そんなこんなで、親子リレーションにより己が何なのかを判定したり親や子のIDを簡素に知ったり表示することができます。
複製
バージョンを作るとは複製を作ることです。まずレコードを複製し、次にパスを元にメディアファイルをオブジェクトフィールドに「挿入」します。ポータル(リレーションされたメタデータ)の内容は複製の必要ありません。複製後再生成します。
さて、オブジェクトの格納場所ですが、バージョンがない頃は次のような格納場所でした。
"Masters/" & Year ( レコード作成日 ) & "/" & Right ( "0" & Month ( レコード作成日 ) ; 2 ) & "/"
Masters というフォルダ以下に格納されますが、バージョンはマスターじゃないので分ける必要があります。いや必要ないけど、ここは心意気として分けておかないと。
Case ( parent_id > 0 ; "Versions/" & Year ( レコード作成日 ) & "/" & parent_id & "/" ; "Masters/" & Year ( レコード作成日 ) & "/" & Right ( "0" & Month ( レコード作成日 ) ; 2 ) & "/" )
オブジェクトの格納場所を変更しました。バージョンの場合 Versions フォルダのIDフォルダに入ります。
上記でOKなわけですが、いや、何かが気に入りません。
ファイル名
気に入らないのは複製メディアのファイル名です。複製元と同じ名前というのはいただけません。複製であることを名前で示しましょう。ファイル名に「version」を足します。
複製を作る前に、バージョンファイルのパスを作っておきます。複製元のパスを記憶に留め、それを少し変形させてバージョンのパスを作成し、その後複製の処理を行います。
- FMパスのファイル名部分の「.拡張子」を「 version.拡張子」で置き換えます。$newFMパス
- レコードを複製した後、オブジェクトフィールドに $newFMパスを挿入すればできあがり。
大体これでOKですが、まだ駄目です。バージョンは複数作れますからね。連番を付与したいんです。
バージョン名連番
完璧な連番は難しいので雑な連番で行きます。つまりバージョン仲間を数えて番号にします。もし同じ親から作られたバージョンが2つあれば、新たに作るバージョンは3ですので「version-3」をファイル名に追加します。
- parent_id がIDと一致する子=バージョンのレコードを検索します
- 該当なしなら既存のバージョンがないので$番号は 1 で決定
- 該当があれば対象レコード数+1を $番号 とし、これをカウンタにループを回します。
- 「 version-$番号」を変数に作成し、同じ「 version-$番号」が既存バージョン名に含まれないか確認します。もしあればさらに$番号を +1 します。
- 含まれないことを確認した時点でループを抜けます。
雑な番号というのは、必ずしも既存バージョンの数と番号が一致しない可能性があるからです。バージョンを作ってもう一個作って最初のを削除すれば、既存バージョン数は1個ですがバージョン番号2のファイルが残ります。こういうケースがあるので、version-2 のファイルがある以上、新規バージョンの名前は version-3となります。
という、こだわりがあるのないのかよくわからない雑な version-番号 をファイル名に追加したパスで、改めて複製を行います。
実践
バージョンが作成された後はどう表示するか、どのように利用するかです。親子リレーションを元にポータル表示を実装したのがインフォパネルのバージョンタブです。
親からバージョンを検索したり、バージョンから親を検索したり、簡素なスクリプトをいくつか作ってボタンに配置したりします。
あとはバージョンに対して編集するスクリプトをあれこれ作っていくことが実践となります。
ファイルを変更するスクリプトの必須手順
バージョンは格納で登録していますから直接ファイルを変更すれば崩壊しておじゃんになります。ですので何をやるにしろ手順を踏む必要があります。
- メディアを余所に複製する
- 編集する
- 編集したメディアをオブジェクトフィールドに[挿入]する
- 余所に作成したメディアを削除する
- 挿入した編集済みメディアのファイル属性やメタデータを再度取得し直す
ファイルを編集するスクリプトを作る際にはこの手順が必須です。
バージョンを格納にしたせいで余計なステップが増えたように見えますが、バージョンかどうかに関わらず格納ファイルを編集するときにはいずれにしても必須な手順です。
ファイルを変更するスクリプトを作成することに関して、そのレコードがバージョンかどうかは関係ありません。バージョンじゃないレコードを編集しようとする際に「オリジナルだけど良いの?」と警告する程度のことです。
以上、バージョンについてでした。FMメディア管理の作り方シリーズではR14(旧実作編ではv5)で採用されました。