123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- class Dir
- def self.mkdir_p(name)
- sub = ""
- parts = name.split('/').reject { |e| e.empty? }
- parts.each do | part |
- sub << "/#{part}"
- mkdir sub
- end
- end
- end
- # Module to help with serialization and deserialization of any type of data
- module Serdes
-
- module ClassMethods
- def serdes_add_to_fields(name, type = nil)
- @serdes_fields ||= []
- info = { :name => name, :type => type }
- @serdes_fields << info
- end
-
- def serdes_reader(name, type = nil)
- serdes_add_to_fields(name, type)
- attr_reader(name)
- end
-
- def serdes_writer(name)
- serdes_add_to_fields(name, type = nil)
- attr_writer(name)
- end
-
- def serdes_accessor(name)
- serdes_add_to_fields(name, type)
- attr_accessor(name)
- end
-
- def serdes_fields()
- @serdes_fields ||= []
- return @serdes_fields
- end
-
-
- def serdes_register(obj)
- @serdes_loaded ||= {}
- @serdes_loaded[obj.id] = obj
- end
-
- def serdes_forget(id)
- @serdes_loaded ||= {}
- @serdes_loaded.delete(id)
- end
-
- def serdes_loaded()
- @serdes_loaded ||= {}
- return @serdes_loaded
- end
-
- def serdes_get(id)
- @serdes_loaded ||= {}
- return @serdes_loaded[id.to_sym]
- end
-
- def serdes_load(id)
- return nil unless id && !id.empty?
-
- full_name = Serdes.serdes_dir_name(self, id) + '/' + Serdes.serdes_file_name(self, id)
- data, errors = Sitef.load_filename(full_name)
- unless data
- log errors.join(", ")
- return nil
- end
-
- eldat = data.select do |el|
- el['id'].to_s == id.to_s
- end
- return nil unless eldat
- eldat = eldat.first
- return nil unless eldat
-
- typedat = {}
- self.serdes_fields.each do |info|
- name = info[:name]
- type = info[:type]
- value = eldat[name.to_s]
-
- typevalue = nil
-
- if type.respond_to?(:serdes_load)
- typevalue = type.serdes_load(value)
- elsif type && Kernel.respond_to?(type.to_sym)
- typevalue = Kernel.send(type.to_sym, value) rescue nil
- else
- typevalue = value
- end
-
- typedat[name] = typevalue
- end
-
- obj = self.new(typedat)
- return obj
- end
-
- def serdes_fetch(id)
- res = serdes_get(id)
- return res if res
- return serdes_load(id)
- end
-
- alias :fetch :serdes_fetch
- alias :load :serdes_load
- alias :get :serdes_get
-
- def from_serdes(id)
- return serdes_fetch(id)
- end
-
- def to_serdes(value)
- return value.id.to_s
- end
- end
- # include callback, be sure to extend the class with the ClassMethods
- def self.included(klass)
- klass.extend(ClassMethods)
- end
-
- def self.serdes_dir_name(klass, id)
- top = klass.to_s.gsub('::', '/').downcase
- top << '/'
- top << id.to_s[0]
- top << '/'
- top << id.to_s
- return top
- end
-
- def self.serdes_file_name(klass, id)
- top = id.to_s.dup
- top << '.'
- top << klass.to_s.gsub('::', '.').downcase
- return top
- end
- def serdes_data
- data = {}
- self.class.serdes_fields.each do |info|
- name = info[:name]
- type = info[:type]
- type||= String
- key = "#{name}"
- value = "#{self.send(name.to_sym)}"
- if type.respond_to?(:to_serdes)
- wrapvalue = type.to_serdes(value)
- else
- wrapvalue = value.to_s
- end
- data[key] = wrapvalue
- end
- return data
- end
-
- def save
- Dir.mkdir_p Serdes.serdes_dir_name(self.class, self.id)
- data = serdes_data
- full_name = Serdes.serdes_dir_name(self.class, self.id) +
- '/' + Serdes.serdes_file_name(self.class, self.id)
- Sitef.save_filename(full_name, [ data ] )
- end
-
- def initialize(fields = {})
- fields.each do |key, value|
- p "Setting #{key} #{value}"
- instance_variable_set("@#{key}", value)
- end
- self.class.serdes_register(self)
- end
- end
|