Storage Mixer
Dejavu's Storage Managers are not only customizable, but chainable. The CachingProxy? class, for example, can pass requests and data through to any other Storage Manager, effectively caching the data transparently.
Sometimes, you want a Manager that is more aware of its data. For example, I needed to mix Transaction data from two different stores, one for Income and one for Expenses, and treat them as if they came from the same table. Here's an SM which mixes the data from the two sources.
class TransactionMixer(storage.StorageManager): """StorageManager for mixing Income from one SM with Expenses from another SM.""" def __init__(self, name, arena, allOptions={}): storage.StorageManager.__init__(self, name, arena, allOptions) self.income_store = arena.stores[allOptions['Income Store']] self.expense_store = arena.stores[allOptions['Expense Store']] def recall(self, unitClass, expr=None): for unit in self.income_store.recall(unitClass, expr): yield unit for unit in self.expense_store.recall(unitClass, expr): yield unit def save(self, unit, forceSave=False): """Update storage from the Unit's data.""" if unit.dirty() or forceSave: self.store(unit).save(unit, forceSave) def destroy(self, unit): """Delete the unit.""" self.store(unit).destroy(unit) def reserve(self, unit): self.store(unit).reserve(unit) def create_storage(self, unitClass): self.store(unit).create_storage(unitClass) def store(self, unit): cls = unit.__class__.__name__ if cls == 'Transaction' and unit.Expense: return self.expense_store elif cls == 'Ledger' and unit.Transaction().Expense: return self.expense_store return self.income_store
It's pretty simple; it doesn't handle relocating a Unit from one store to the other, for example. But I didn't have a use case for that. You could certainly build that functionality into your own Storage Manager if necessary. It also requires that Transaction.Expense and Ledger.TransactionID be set correctly, for every call. But that's so much easier to enforce in the presentation layer on a small project, than to solve in the general case in the Storage Manager, that the simpler solution won out.
