serdes.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. class Dir
  2. def self.mkdir_p(name)
  3. sub = ""
  4. parts = name.split('/').reject { |e| e.empty? }
  5. parts.each do | part |
  6. sub << "/#{part}"
  7. mkdir sub
  8. end
  9. end
  10. end
  11. # Module to help with serialization and deserialization of any type of data
  12. module Serdes
  13. module ClassMethods
  14. def serdes_add_to_fields(name, type = nil)
  15. @serdes_fields ||= []
  16. info = { :name => name, :type => type }
  17. @serdes_fields << info
  18. end
  19. def serdes_reader(name, type = nil)
  20. serdes_add_to_fields(name, type)
  21. attr_reader(name)
  22. end
  23. def serdes_writer(name)
  24. serdes_add_to_fields(name, type = nil)
  25. attr_writer(name)
  26. end
  27. def serdes_accessor(name)
  28. serdes_add_to_fields(name, type)
  29. attr_accessor(name)
  30. end
  31. def serdes_fields()
  32. @serdes_fields ||= []
  33. return @serdes_fields
  34. end
  35. def serdes_register(obj)
  36. @serdes_loaded ||= {}
  37. @serdes_loaded[obj.id] = obj
  38. end
  39. def serdes_forget(id)
  40. @serdes_loaded ||= {}
  41. @serdes_loaded.delete(id)
  42. end
  43. def serdes_loaded()
  44. @serdes_loaded ||= {}
  45. return @serdes_loaded
  46. end
  47. def serdes_get(id)
  48. @serdes_loaded ||= {}
  49. return @serdes_loaded[id.to_sym]
  50. end
  51. def serdes_load(id)
  52. return nil unless id && !id.empty?
  53. full_name = Serdes.serdes_dir_name(self, id) + '/' + Serdes.serdes_file_name(self, id)
  54. data, errors = Sitef.load_filename(full_name)
  55. unless data
  56. log errors.join(", ")
  57. return nil
  58. end
  59. eldat = data.select do |el|
  60. el['id'].to_s == id.to_s
  61. end
  62. return nil unless eldat
  63. eldat = eldat.first
  64. return nil unless eldat
  65. typedat = {}
  66. self.serdes_fields.each do |info|
  67. name = info[:name]
  68. type = info[:type]
  69. value = eldat[name.to_s]
  70. typevalue = nil
  71. if type.respond_to?(:serdes_load)
  72. typevalue = type.serdes_load(value)
  73. elsif type && Kernel.respond_to?(type.to_sym)
  74. typevalue = Kernel.send(type.to_sym, value) rescue nil
  75. else
  76. typevalue = value
  77. end
  78. typedat[name] = typevalue
  79. end
  80. obj = self.new(typedat)
  81. return obj
  82. end
  83. def serdes_fetch(id)
  84. res = serdes_get(id)
  85. return res if res
  86. return serdes_load(id)
  87. end
  88. alias :fetch :serdes_fetch
  89. alias :load :serdes_load
  90. alias :get :serdes_get
  91. def from_serdes(id)
  92. return serdes_fetch(id)
  93. end
  94. def to_serdes(value)
  95. return value.id.to_s
  96. end
  97. end
  98. # include callback, be sure to extend the class with the ClassMethods
  99. def self.included(klass)
  100. klass.extend(ClassMethods)
  101. end
  102. def self.serdes_dir_name(klass, id)
  103. top = klass.to_s.gsub('::', '/').downcase
  104. top << '/'
  105. top << id.to_s[0]
  106. top << '/'
  107. top << id.to_s
  108. return top
  109. end
  110. def self.serdes_file_name(klass, id)
  111. top = id.to_s.dup
  112. top << '.'
  113. top << klass.to_s.gsub('::', '.').downcase
  114. return top
  115. end
  116. def serdes_data
  117. data = {}
  118. self.class.serdes_fields.each do |info|
  119. name = info[:name]
  120. type = info[:type]
  121. type||= String
  122. key = "#{name}"
  123. value = "#{self.send(name.to_sym)}"
  124. if type.respond_to?(:to_serdes)
  125. wrapvalue = type.to_serdes(value)
  126. else
  127. wrapvalue = value.to_s
  128. end
  129. data[key] = wrapvalue
  130. end
  131. return data
  132. end
  133. def save
  134. Dir.mkdir_p Serdes.serdes_dir_name(self.class, self.id)
  135. data = serdes_data
  136. full_name = Serdes.serdes_dir_name(self.class, self.id) +
  137. '/' + Serdes.serdes_file_name(self.class, self.id)
  138. Sitef.save_filename(full_name, [ data ] )
  139. end
  140. def initialize(fields = {})
  141. fields.each do |key, value|
  142. p "Setting #{key} #{value}"
  143. instance_variable_set("@#{key}", value)
  144. end
  145. self.class.serdes_register(self)
  146. end
  147. end