class WAB::Impl::Model
The Model
class is used to store data when using the WAB::Impl::Shell
. It is not intended for any other use. The get and query methods are the primary means of interacting with the model.
The Model
is simple in that it stores data in a Hash references by ref numbers. Data
is stores in a directory as separate JSON files that are named as the ref number as a 16 character hexidecimal.
Public Class Methods
new(dir, indent=0)
click to toggle source
Create a new Model
using the designated directory as the store.
- dir
-
directory to store data in
# File lib/wab/impl/model.rb, line 20 def initialize(dir, indent=0) @dir = dir.nil? ? nil : File.expand_path(dir) @cnt = 0 @indent = indent @map = {} @lock = Thread::Mutex.new FileUtils.mkdir_p(@dir) unless @dir.nil? || Dir.exist?(@dir) load_files unless @dir.nil? end
Public Instance Methods
get(ref)
click to toggle source
Get a single record in the database. A WAB::Impl::Data
object is returned if not nil.
- ref
-
references number of the object to retrieve.
# File lib/wab/impl/model.rb, line 34 def get(ref) @map[ref] end
query(tql)
click to toggle source
Execute a TQL query.
_Note that the current implementation does not support nested data retrieval.
- tql
-
query to execute
# File lib/wab/impl/model.rb, line 44 def query(tql) rid = tql[:rid] where = nil filter = nil if tql.has_key?(:where) w = tql[:where] where = w.is_a?(Array) ? ExprParser.parse(w) : w end filter = ExprParser.parse(tql[:filter]) if tql.has_key?(:filter) if tql.has_key?(:insert) insert(tql[:insert], rid, where, filter) elsif tql.has_key?(:update) update(tql[:update], rid, where, filter) elsif tql.has_key?(:delete) delete(tql[:delete], rid, where, filter) else select(tql[:select], rid, where, filter) end end
Private Instance Methods
delete(_del_opt, _rid, where, filter)
click to toggle source
# File lib/wab/impl/model.rb, line 139 def delete(_del_opt, _rid, where, filter) deleted = [] @lock.synchronize { if where.is_a?(Expr) @map.each { |ref,obj| if where.eval(obj) && (filter.nil? || filter.eval(obj)) deleted << ref @map.delete(ref) end } # A reference. elsif !@map.delete(where).nil? deleted << where remove_file(where) end } { code: 0, deleted: deleted } end
extract_matches(format, ref, rid, obj)
click to toggle source
# File lib/wab/impl/model.rb, line 89 def extract_matches(format, ref, rid, obj) if format.nil? { id: ref, data: obj.native } else format_obj(format, ref, rid, obj) end end
format_obj(format, ref, rid, obj)
click to toggle source
# File lib/wab/impl/model.rb, line 158 def format_obj(format, ref, rid, obj) case format when Hash native = {} format.each { |k,v| native[k] = format_obj(v, ref, rid, obj) } native when Array format.map { |v| format_obj(v, ref, rid, obj) } when String if '$ref' == format ref elsif '$rid' == format rid elsif '$' == format || '$root' == format obj.native elsif !format.empty? && format.start_with?("'") format[1..-1] else obj.get(format) end else format end end
insert(obj, rid, where, filter)
click to toggle source
# File lib/wab/impl/model.rb, line 67 def insert(obj, rid, where, filter) ref = nil @lock.synchronize { unless where.nil? @map.each_value { |v| if where.eval(v) && (filter.nil? || filter.eval(v)) result = { code: -1, error: 'Already exists.' } result[:rid] = rid unless rid.nil? return result end } end @cnt += 1 ref = @cnt @map[ref] = Data.new(obj, true) write_to_file(ref, obj) } result = { code: 0, ref: ref } result[:rid] = rid unless rid.nil? result end
load_files()
click to toggle source
# File lib/wab/impl/model.rb, line 183 def load_files() Dir.foreach(@dir) { |fn| next if '.' == fn[0] ref = fn[0..-6] iref = ref.to_i(16) @cnt = iref if @cnt < iref @map[iref] = Data.new(Oj.load_file(File.join(@dir, fn), mode: :wab), true) } end
remove_file(ref)
click to toggle source
# File lib/wab/impl/model.rb, line 199 def remove_file(ref) File.delete(File.join(@dir, "%016x.json" % ref)) unless @dir.nil? end
select(format, rid, where, filter)
click to toggle source
# File lib/wab/impl/model.rb, line 97 def select(format, rid, where, filter) matches = [] @lock.synchronize { if where.nil? && filter.nil? @map.each { |ref,obj| matches << extract_matches(format, ref, rid, obj) } else @map.each { |ref,obj| if where.eval(obj) && (filter.nil? || filter.eval(obj)) matches << extract_matches(format, ref, rid, obj) end } end } result = { code: 0, results: matches } result[:rid] = rid unless rid.nil? result end
update(obj, _rid, where, filter)
click to toggle source
# File lib/wab/impl/model.rb, line 117 def update(obj, _rid, where, filter) updated = [] @lock.synchronize { if where.is_a?(Expr) # TBD must be able to update portions of an object @map.each_pair { |ref, v| if where.eval(v) && (filter.nil? || filter.eval(v)) @map[ref] = Data.new(obj, true) updated << ref write_to_file(ref, obj) end } else # A reference. @map[where] = Data.new(obj, true) updated << where write_to_file(where, obj) end } { code: 0, updated: updated } end
write_to_file(ref, obj)
click to toggle source
# File lib/wab/impl/model.rb, line 193 def write_to_file(ref, obj) return if @dir.nil? obj.native if obj.is_a?(WAB::Data) File.open(File.join(@dir, "%016x.json" % ref), 'wb') { |f| f.write(Oj.dump(obj, mode: :wab, indent: @indent)) } end