はじめにOctopusがいて...
public class Octopus: Object {
public dynamic var legs: Int
}
途中からHumanが現れて、forefootsを持っている。
public class Octopus: Object {
public dynamic var legs: Int
}
public class Human: Object {
public dynamic var forefoots: Int
}
これからHumanのforefootsをarmsにリネームしたい。
public class Octopus: Object {
public dynamic var legs: Int
}
public class Human: Object {
public dynamic var arms: Int // Renamed to from "forefoots" in schemeVersion 2017
}
そこでマイグレーション処理( renameProperty(onType:from:)
)を書きたいのですが、RealmがまだOctopusしかいなかった時代から突然やって来ると、そもそもHumanが存在しないので、 renameProperty(onType:from:)
できません。
let migrationBlock: RLMMigrationBlock = { migration, oldSchemaVersion in
/** ... */
if oldSchemaVersion < 2017 {
// Humanのforefootsをarmsにリネームする。
// FIXME: アプリがHumanの居ない時代から来るとここで
// Cannot rename property 'Human.forefoots' because it does not exist."
// となってマイグレーションに失敗してしまいます。
migration.renameProperty(onType: Human.className(), from: "forefoots", to: "arms")
}
}
- HumanがいつのschemaVersionから存在していたのかを突き止め、
renameProperty(onType:from:)
を判断する条件文に追加すべきでしょうか?- schemaVersionで条件判定するのではなく、テーブル(ObjectSchema?)が存在=リネーム対象があるならば
renameProperty(onType:from:)
を行う、というような書き方は可能ですか?
- schemaVersionで条件判定するのではなく、テーブル(ObjectSchema?)が存在=リネーム対象があるならば
- schemaVersionで条件判定できればそれで安心ですか? : "Octopusの定義はずっと存在していたが、レコードを作ったことは一度も無かった"という時、Octopusに対して
renameProperty(onType:from:)
をしようとするとどうなってしまいますか?- Realmのテーブルが何をきっかけに生成されるのか理解していません。一度も保存したことがないモデルはテーブルが存在せず、バージョンで判別しても
renameProperty(onType:from:)
できない、ということは起き得ますか?- (もし起きるのであれば)基本的に
renameProperty(onType:from:)
の前には存在チェックが必要でしょうか?それは不要でしょうか?
- (もし起きるのであれば)基本的に
- Realmのテーブルが何をきっかけに生成されるのか理解していません。一度も保存したことがないモデルはテーブルが存在せず、バージョンで判別しても
これでテーブルの存在を確認できそうですが、間違いないでしょうか。あるいは、もうすこし簡単な方法はありますか?
let shouldRename: Bool = migration.oldSchema.objectSchema.reduce(false) { result, scheme in
return result || scheme.className == Human.className()
}
reduceよりfirst(where:)使ったほうが良さそうなのでコメントしてある。 https://gist.github.com/niwatako/77cdca9f27569fc5498b2ff9ae6db87b#gistcomment-2041941
- Realm社の岸川さんにコメントでご回答を頂いた
- https://gist.github.com/niwatako/77cdca9f27569fc5498b2ff9ae6db87b#gistcomment-2042413 - マイグレーション処理が要らないschemaの追加やプロパティの追加でも、プロパティのリネームを見越すとどのschemaVersionで追加されたか記録しておくべきである
- 管理できていなかったら、しょうがないので上記の存在チェックをする方法でもよい。
つまりこういうのが理想
let migrationBlock: RLMMigrationBlock = { migration, oldSchemaVersion in
/** ... */
if oldSchemaVersion < 2017 {
/** ... */
// 2017へのマイグレーションならforefootsをリネームしたいけど、Humanが存在するのは1017以降なのでそのときだけリネーム
if 1017 <= oldSchemaVersion {
migration.renameProperty(onType: Human.className(), from: "forefoots", to: "arms")
}
}
}
最後の方法でやるにしても、こうした方が良いかもしれない(些細)