RealmのschemaVersion
Realmのドキュメントのマイグレーション項目で言及されている通り、Realmを扱う際にはRealm.Configuration
の引数であるschemaVersion
にモデルにアップデートがあった際に以前のバージョンよりも大きい値を設定する必要があります。なお、この値はマイグレーションなどの処理を行う際に必要となり、Realm内部でoldSchemaVersion
(初期値0)よりも最新のschemaVersion
が大きいか否かで自動的にマイグレーションされます。(データ移行の際はmigrationBlock
で移行処理を記述する)
schemaVersionをどのように管理すべきか
方法1. モデルのアップデートを行う際に手元でschemaVersionをインクリメントする
個人的にオススメしません。複数人で開発していた際に同時にアップデートすることもあるかと思います。その際にコンフリクトしたり、配信されているとschemaVersion
が正しくインクリメントされておらずクラッシュも起きうると考えられます。
方法2. ビルド番号を直接入れる
アプリバージョンに関わらず、ビルド番号をGitのコミット数などでインクリメントしている場合、ビルド番号をschemaVersion
に入れることも方法の1つかと思います。この場合だと実装者に関わらず常にインクリメントされていくのでschemaVersion
も自動で上がってくれます。この方法がお手軽ですが、モデルにアップデートがないのにも関わらずインクリメントされるのは違和感に感じます。また、ビルド番号をどのように管理しているかにも依存するので開発方針に左右されます。
以上の方法を踏まえて実現したい理想
-
schemaVersion
はモデルのアップデートが行われた際のみインクリメントしたい。 - 複数人開発においても正しく管理されるようにGitに依存した値を注入したい
モデルのディレクトリ以下のgit logからschemaVersionを設定する
最終的にfastlaneのlaneとして定義できるようにします。
Step1. 特定のディレクトリ以下のマージコミットを取得する
git log --oneline --merges --first-parent master -- DIR_PATH | wc -l
上記のコマンドでDIR_PATH
上の変更に対するマージコミットのカウントが取れます。
DIR_PATHはモデルが存在するディレクトリです。最終的にはこの数を最新のschemaVersion
として設定します。
Step2. 現在のブランチの最新マージコミット(コミットハッシュ)を取得する
git log --oneline --merges --pretty=format:"%h" -1
取得したコミットハッシュをHASH_STEP2
とします。
Step3. 現在のブランチの最新コミット(コミットハッシュ)を取得する
git log --oneline --pretty=format:"%h" -1
取得したコミットハッシュをHASH_STEP3
とします。
Step4. 最新のマージコミットと現在のコミット間で特定ディレクトリ上の変更のコミット数を取得する
git log --oneline HASH_STEP2..HASH_STEP3 -- DIR_PATH | wc -l
これによってDIR_PATH
において現在、変更を行ったかが0かどうかで判断することができます。
Step5. Step1~4を用いてlaneを組む
lane :bump_schema_version do
latest_merges_commit_hash = sh(%Q[git log --oneline --merges --pretty=format:"%h" -1])
latest_commit_hash = sh(%Q[git log --oneline --pretty=format:"%h" -1])
latest_model_commit_count = sh(%Q[git log --oneline #{latest_merges_commit_hash}..#{latest_commit_hash} -- DIR_PATH | wc -l]).strip!.to_i
latest_schema_version = sh("git log --oneline --merges --first-parent master -- DIR_PATH | wc -l").strip!.to_i
if latest_model_commit_count > 0
latest_schema_version += 1
end
set_info_plist_value(path: PLIST_PATH, key: "schemaVersion", value: latest_schema_version)
end
set_info_plist_value
でInfo.plist内のschemaVersion
に書き込み、コードから取得することでRealm.Configuration
に渡すことができます。
このlaneを実行することで現在のブランチで変更があるかを取得することができます。
latest_schema_version
をmasterへのマージコミット数としているのはCI上で実行したときにはモデルのディレクトリにおける変更のmasterマージコミット数をschemaVersion
とするためです。
まだマージしていないブランチ上で実行したときにはStep4で行っている現在変更しているかを加味してlatest_schema_version
がインクリメントされます。
前者と後者の値は一致するので「手元で実行してPR作成によってインクリメントする」or「CI上でフックして実行、PR作成する」などインクリメントする方法を選択することができます。
最後に
schemaVersion
の管理方法をどのようにするかはプロジェクトによっても変わりますし、悩ましい部分だと思います。
他の方法もあればぜひ教えてください!