diff options
Diffstat (limited to 'acf/model')
-rw-r--r-- | acf/model/field.lua | 4 | ||||
-rw-r--r-- | acf/model/init.lua | 9 | ||||
-rw-r--r-- | acf/model/model.lua | 35 | ||||
-rw-r--r-- | acf/model/node.lua | 40 | ||||
-rw-r--r-- | acf/model/set.lua | 49 |
5 files changed, 92 insertions, 45 deletions
diff --git a/acf/model/field.lua b/acf/model/field.lua index 7e3aa1d..436ce2c 100644 --- a/acf/model/field.lua +++ b/acf/model/field.lua @@ -117,12 +117,14 @@ function TreeNode:save(context, value) local errors = err.ErrorDict() for k, v in pairs(value) do - errors:collect(function() new[k] = v end) + errors:collect(self.save_member, new, k, v) end errors:raise() end end +function TreeNode.save_member(node, k, v) node[k] = v end + Model = class(TreeNode) diff --git a/acf/model/init.lua b/acf/model/init.lua index bf4f7b4..2800ab6 100644 --- a/acf/model/init.lua +++ b/acf/model/init.lua @@ -17,6 +17,7 @@ new = model.new local to_field = model.to_field node = require('acf.model.node') +set = require('acf.model.set') local object = require('acf.object') local class = object.class @@ -196,11 +197,9 @@ function Collection:load(context) end -PrimitiveList = class(Collection) - -function PrimitiveList:init(params) - super(self, PrimitiveList):init(params, node.PrimitiveList) -end +Set = class(Collection) +function Set:init(params) super(self, Set):init(params, set.Set) end +function Set.save_member(node, k, v) set.add(node, v) end -- experimental diff --git a/acf/model/model.lua b/acf/model/model.lua index 5fd96a7..7c27b50 100644 --- a/acf/model/model.lua +++ b/acf/model/model.lua @@ -71,22 +71,7 @@ function Model:init(context) function mt.mmeta(name) return mt.field(name):meta() end - mt.meta = {type='model', - fields=util.map(function(f) return mt.mmeta(f) end, - self._fields)} - - function mt.members() - 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) + function mt.get(k) local f = mt.field(k) if f then if f.compute then return f:compute() end @@ -95,9 +80,25 @@ function Model:init(context) return mt.class[k] end - function mt.__newindex(t, k, v) + function mt.set(k, v) local f = mt.field(k) if not f then raise(mt.path, 'Field named '..k..' does not exist') end f:save(v) end + + mt.meta = { + type='model', + fields=util.map(function(f) return mt.mmeta(f) end, self._fields) + } + + function mt.members() + 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 end diff --git a/acf/model/node.lua b/acf/model/node.lua index 7a818be..cf3111d 100644 --- a/acf/model/node.lua +++ b/acf/model/node.lua @@ -52,6 +52,11 @@ TreeNode = class() function TreeNode:init(context) local mt = getmetatable(self) update(mt, context) + + function mt.set(k, v) rawset(self, k, v) end + function mt.__index(t, k) return mt.get(k) end + function mt.__newindex(t, k, v) mt.set(k, v) end + mt.txn.validable[mt.path] = mt.addr end @@ -88,28 +93,8 @@ function Collection:init(context, params) 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 -end - - -PrimitiveList = class(Collection) - -function PrimitiveList:init(context, params) - super(self, PrimitiveList):init(context, params) - - local mt = getmetatable(self) - local index = mt.__index - - function mt.__index(t, k) - if type(k) == 'number' then return index(t, k) end - - for i, j in ipairs(mt.txn:get(mt.addr) or {}) do - assert(i == tonumber(j)) - if mt.field:load(i) == k then return k end - end - raise(mt.path, 'Value does not exist: '..k) - end + function mt.get(k) return mt.field:load(k) end + function mt.set(k, v) mt.field:save(k, v) end end @@ -138,3 +123,14 @@ mmeta = meta_func('mmeta') parent = meta_func('parent') path = meta_func('path') validate = meta_func('validate') + + +local rawpairs = pairs + +function pairs(tbl) + if not object.isinstance(tbl, TreeNode) then return rawpairs(tbl) end + local mt = getmetatable(tbl) + local res = {} + for _, member in ipairs(mt.members()) do res[member] = mt.get(member) end + return rawpairs(res) +end diff --git a/acf/model/set.lua b/acf/model/set.lua new file mode 100644 index 0000000..be6c2de --- /dev/null +++ b/acf/model/set.lua @@ -0,0 +1,49 @@ +--[[ +Copyright (c) 2012-2013 Kaarle Ritvanen +See LICENSE file for license details +--]] + +module(..., package.seeall) + +local TreeNode = require('acf.model.field').TreeNode +local npairs = require('acf.model.node').pairs +local object = require('acf.object') + + +local function find(set, value) + for i, member in npairs(set) do + if member == value then return i end + end +end + + +Set = object.class(require('acf.model.node').Collection) + +function Set:init(context, params) + assert(not object.isinstance(params.field, TreeNode)) + object.super(self, Set):init(context, params) + + local mt = getmetatable(self) + mt.meta.type = 'set' + + function mt.__index(t, k) return find(self, k) and k end + + function mt.__newindex(t, k, v) + assert(v == nil) + local i = find(self, k) + if not i then return end + + local len = #mt.members() + while i < len do + mt.set(i, mt.get(i + 1)) + i = i + 1 + end + mt.set(len, nil) + end +end + + +function add(set, value) + local mt = getmetatable(set) + if not find(set, value) then mt.set(#mt.members() + 1, value) end +end |