require 'yaml' require 'fileutils' require 'og/store' module Og # A Store that saves the object on the Filesystem. # An extension of the Memory store. class FilesysStore < Store # :section: Store methods. def self.dir(name) "#{name}_db" end def self.create(options) name = dir(options[:name]) FileUtils.mkdir_p(name) rescue Logger.error "Cannot create '#{name}'" end def self.destroy(options) name = dir(options[:name]) FileUtils.rm_rf(name) rescue Logger.error "Cannot destroy '#{name}'" end # Initialize a connection to this store. def initialize(options) super @base_dir = self.class.dir(options[:name]) unless File.directory?(@base_dir) Logger.info "Database '#{options[:name]}' not found!" self.class.create(options) end end def enchant(klass, manager) super klass.const_set 'OGNAME', klass.to_s.gsub(/::/, "/").downcase klass.property :oid, Fixnum FileUtils.mkdir_p(path(klass)) File.open(spath(klass), 'w') { |f| f << '1' } rescue => ex Logger.error "Cannot create directory to store '#{klass}' classes!" end # :section: Lifecycle methods. def load(oid, klass) obj = nil File.open(path(klass, oid), 'r') { |f| obj = YAML::load(f.read) } return obj rescue return nil end def reload(obj) end def save(obj) seq = nil File.open(spath(obj.class), 'r') { |f| seq = f.read.to_i } obj.oid = seq File.open(path(obj.class, obj.oid), 'w') { |f| f << obj.to_yaml } seq += 1 File.open(spath(obj.class), 'w') { |f| f << seq } end def delete(obj_or_pk, klass = nil, cascade = true) pk = obj_or_pk.is_a?(Fixnum) ? obj_or_pk : obj_or_pk.oid klass ||= obj_or_pk.class FileUtils.rm(path(klass, pk)) end def find end def count end private # Path helper. def path(klass, pk = nil) class_dir = File.join(@base_dir, klass::OGNAME) pk ? File.join(class_dir, "#{pk}.yml") : class_dir end # Path to sequence helper. def spath(klass) File.join(path(klass), 'seq') end end end