diff options
Diffstat (limited to 'acf')
-rw-r--r-- | acf/model/model.lua | 17 | ||||
-rw-r--r-- | acf/model/node.lua | 19 | ||||
-rw-r--r-- | acf/transaction/init.lua | 33 | ||||
-rw-r--r-- | acf/util.lua | 8 |
4 files changed, 49 insertions, 28 deletions
diff --git a/acf/model/model.lua b/acf/model/model.lua index 6a9a843..aa27312 100644 --- a/acf/model/model.lua +++ b/acf/model/model.lua @@ -79,6 +79,13 @@ function Model:init(txn, path, addr) return util.map(function(f) return f.name end, mt.meta.fields) end + function mt.validate() + for _, name in ipairs(mt.members()) do + local field = mt.field(name) + if not field.compute then field:validate_saved() end + end + end + function mt.__index(t, k) local f = mt.field(k) if f then @@ -93,14 +100,4 @@ function Model:init(txn, path, addr) if not f then raise(mt.path, 'Field named '..k..' does not exist') end f:save(v) end - - txn.validate[mt.path] = function() self:validate() end -end - -function Model:validate() - local mt = getmetatable(self) - for _, name in ipairs(mt.members()) do - local field = mt.field(name) - if not field.compute then field:validate_saved() end - end end diff --git a/acf/model/node.lua b/acf/model/node.lua index 3459fce..f893d6a 100644 --- a/acf/model/node.lua +++ b/acf/model/node.lua @@ -48,6 +48,8 @@ function TreeNode:init(txn, path, addr) mt.txn = txn mt.path = path mt.addr = addr + + txn.validable[path] = true end function TreeNode:search(path) @@ -67,14 +69,6 @@ Collection = class(TreeNode) function Collection:init(txn, path, addr, field, required) super(self, Collection):init(txn, path, addr) - if required then - txn.validate[path] = function() - if #txn:get(addr) == 0 then - raise(path, 'Collection cannot be empty') - end - end - end - self.init = nil self.search = nil @@ -84,6 +78,14 @@ function Collection:init(txn, path, addr, field, required) mt.meta = {type='collection', members=mt.field:meta('$')} function mt.mmeta(name) return mt.meta.members end function mt.members() return txn:get(addr) or {} end + + function mt.validate() + if required then + if #txn:get(addr) == 0 then + raise(path, 'Collection cannot be empty') + end + end + end function mt.__index(t, k) return mt.field:load(k) end function mt.__newindex(t, k, v) mt.field:save(k, v) end @@ -132,3 +134,4 @@ members = meta_func('members') meta = meta_func('meta') mmeta = meta_func('mmeta') path = meta_func('path') +validate = meta_func('validate') diff --git a/acf/transaction/init.lua b/acf/transaction/init.lua index eb92c34..e9b8bbc 100644 --- a/acf/transaction/init.lua +++ b/acf/transaction/init.lua @@ -11,7 +11,9 @@ local object = require('acf.object') local super = object.super local pth = require('acf.path') local be_mod = require('acf.transaction.backend') -local copy = require('acf.util').copy + +local util = require('acf.util') +local copy = util.copy local function remove_list_value(list, value) @@ -30,7 +32,7 @@ end local Transaction = object.class(be_mod.TransactionBackend) -function Transaction:init(backend) +function Transaction:init(backend, validate) super(self, Transaction):init() self.backend = backend @@ -42,7 +44,8 @@ function Transaction:init(backend) self.modified = {} self.deleted = {} - self.validate = {} + self.validate = validate + self.validable = {} self.root = RootModel(self) end @@ -122,11 +125,15 @@ function Transaction:search(path) return self.root:search(pth.split(path)) end function Transaction:commit() self:check() - local errors = ErrorDict() - for path, func in pairs(self.validate) do - if not self.deleted[path] then errors:collect(func) end + if self.validate then + local errors = ErrorDict() + for path, _ in pairs(copy(self.validable)) do + if not self.deleted[path] then + errors:collect(getmetatable(self:search(path)).validate) + end + end + errors:raise() end - errors:raise() local mods = {} local handled = {} @@ -174,8 +181,18 @@ function Transaction:commit() for path, _ in pairs(self.added) do insert_add(path) end self.backend:comp_and_setm(self.access_time, mods) + + + if not self.validate then + util.update(self.backend.validable, self.validable) + end + self.backend = nil end + local store = require('acf.persistence').DataStore() -function start(txn) return Transaction(txn or store) end + +function start(txn, defer_validation) + return Transaction(txn or store, not (txn and defer_validation)) +end diff --git a/acf/util.lua b/acf/util.lua index 9788c81..9ca287c 100644 --- a/acf/util.lua +++ b/acf/util.lua @@ -10,11 +10,15 @@ function setdefault(t, k, v) return t[k] end -function setdefaults(dst, src) - for k, v in pairs(src) do if dst[k] == nil then dst[k] = v end end +function update(dst, src, preserve) + for k, v in pairs(src) do + if not preserve or dst[k] == nil then dst[k] = v end + end return dst end +function setdefaults(dst, src) return update(dst, src, true) end + function copy(var) return type(var) == 'table' and setdefaults({}, var) or var end |