-
Notifications
You must be signed in to change notification settings - Fork 67
Strategy for MotionModel Persistence
This document refers only to the ArrayModelAdapter branch of MotionModel.
MotionModel is designed to feel like pretty much any ActiveRecord, DataMapper, ActiveModel ORM in the Ruby space. As such, it utilizes a good deal of muscle memory that Rails programmers, in particular, have developed. Beneath the covers, though, the AMA (ArrayModelAdapter) interacts with the backing store far differently than an ORM that wraps a database engine.
To be clear, the whole idea behind MotionModel was to provide a light wrapper around NSCoding but the wrapper evolved I implementation to feel much more like it was talking to a database. That is not what is happening.
Think of your iOS device as having two different "sorts" of memory: volatile (aka RAM or application memory) and non-volatile memory where data is persistent. When you do a save in MotionModel, it's reasonable to expect that you have affected the persistent data store. That's not what happens, however. All of your CRUD operations are cached in volatile memory until you specifically serialize it using one of the serialization APIs.
You might wonder why this implementation decision was made; simple: it's better to have more choice than less when operations that involve some expense are concerned. Serialization, in this context, means the copying of all objects from volatile memory to the backing store. In the small, this doesn't seem like much of a deal. Say a user makes an entry involving 5 fields. It's unlikely they would notice any performance hit if you did both a save and persist. Especially if the data set is small.
However, if your application fetches data remotely, all this copying can become a performance issue. So that drove the decision to separate CRUD operations from persistence, allowing the user discretion with respect to how often data is persisted.
Thus far, the issue has only come up once, but this can be repaired programmatically. Here's a sketch of what it would take:
class MyClass
include MotionModel::Model
include MotionModel::ArrayModelAdapter
include MotionModel::AutoPersist
persists_to 'your/file/path'
persistence_strategy :synchronous_copy # Persist every save, etc.
columns :whatever
endThe new wrinkles here are the new module MotionModel::AutoPersist And some macros it would introduce:
persists_to specifies a file name for the backing store. If not specified, a lowercase pluralized version of the model name is used.
persistence_strategy allows you to choose whether to persist via:
-
:synchronous_copy, options-- Copy and block -
:asynchronous_copy, options-- Copy off main thread
Options are:
-
:change_limit: <threshold>Persists every so often
Finally, you can call persist! at any point should you need to make certain your data is serialized.
To solve the problem of remote hydration, the following APIs are provided:
-
auto_persist_offtemporarily suspends automatic persistence behavior. -
auto_persist_onrestores automatic persistence state to that declared in the model.
Alternatively, you can call:
without_serialization do
# Hydrate the collection
end
This suspends automatic persistence for the duration of the block, restoring it on exit.