serdes.rb 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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)
  103. top = klass.to_s.gsub('::', '/').downcase
  104. return top
  105. end
  106. def self.serdes_file_name(id)
  107. top = id.to_s.dup
  108. top << '.sitef'
  109. return top
  110. end
  111. def serdes_data
  112. data = {}
  113. self.class.serdes_fields.each do |info|
  114. name = info[:name]
  115. type = info[:type]
  116. type||= String
  117. key = "#{name}"
  118. value = "#{self.send(name.to_sym)}"
  119. if type.respond_to?(:to_serdes)
  120. wrapvalue = type.to_serdes(value)
  121. else
  122. wrapvalue = value.to_s
  123. end
  124. data[key] = wrapvalue
  125. end
  126. return data
  127. end
  128. def save
  129. Dir.mkdir_p Serdes.serdes_dir_name(self.class, self.id)
  130. data = serdes_data
  131. full_name = Serdes.serdes_dir_name(self.class, self.id) +
  132. '/' + Serdes.serdes_file_name(self.class, self.id)
  133. Sitef.save_filename(full_name, [ data ] )
  134. end
  135. def initialize(fields = {})
  136. fields.each do |key, value|
  137. p "Setting #{key} #{value}"
  138. instance_variable_set("@#{key}", value)
  139. end
  140. self.class.serdes_register(self)
  141. end
  142. end