serdes.rb 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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_delete(id)
  40. @serdes_loaded ||= {}
  41. @serdes_loaded.delete(id)
  42. end
  43. def serdes_get(id)
  44. @serdes_loaded ||= {}
  45. return @serdes_loaded[id.to_sym]
  46. end
  47. def serdes_load(id)
  48. full_name = serdes_dir_name(self) + '/' + serdes_file_name(self)
  49. data = Sitef.load_filename(full_name)
  50. eldat = data.select do |el|
  51. el['id'] == id
  52. end
  53. return nil unless eldat
  54. typedat = {}
  55. self.serdes_fields.each do |info|
  56. name = info[:name]
  57. type = info[:type]
  58. value = eldat[name]
  59. type||= String
  60. typevalue = nil
  61. if type.respond_to?(:serdes_load)
  62. typevalue = type.serdes_load(value)
  63. elsif Kernel.respond_to?(type)
  64. typevalue = Kernel.send(type, value) rescue nil
  65. else
  66. typevalue = value
  67. end
  68. typedat[key] = typevalue
  69. return self.new(typedat)
  70. end
  71. obj = self.new(typedat)
  72. return obj
  73. end
  74. def serdes_fetch(id)
  75. res = serdes_get(id)
  76. return res if res
  77. return serdes_load(id)
  78. end
  79. def from_serdes(id)
  80. return serdes_fetch(id)
  81. end
  82. def to_serdes(value)
  83. return value.id.to_s
  84. end
  85. end
  86. # include callback, be sure to extend the class with the ClassMethods
  87. def self.included(klass)
  88. klass.extend(ClassMethods)
  89. end
  90. def self.serdes_dir_name(obj)
  91. top = obj.class.to_s.gsub('::', '/').downcase
  92. top << '/'
  93. top << obj.id.to_s[0]
  94. top << '/'
  95. top << obj.id.to_s
  96. return top
  97. end
  98. def self.serdes_file_name(obj)
  99. top = obj.id.to_s.dup
  100. top << '.'
  101. top << obj.class.to_s.gsub('::', '.').downcase
  102. return top
  103. end
  104. def serdes_data
  105. data = {}
  106. self.class.serdes_fetch.each do |info|
  107. name = info[:name]
  108. type = info[:type]
  109. type||= String
  110. key = "#{name}"
  111. value = "#{self.send(name.to_sym)}"
  112. if type.respond_to?(:to_serdes)
  113. wrapvalue = type.to_serdes(value)
  114. else
  115. wrapvalue = value.to_s
  116. end
  117. data[key] = wrapvalue
  118. end
  119. p "serdes_data", data, self.class.serdes_register
  120. return data
  121. end
  122. def save
  123. Dir.mkdir_p Serdes.serdes_dir_name(self)
  124. data = serdes_data
  125. full_name = Serdes.serdes_dir_name(self) + '/' + Serdes.serdes_file_name(self)
  126. Sitef.save_filename(full_name, [ data ] )
  127. end
  128. def initialize(fields = {})
  129. fields.each |key, value| do
  130. instance_variable_set("@#{key}", value)
  131. end
  132. self.klass.serdes_register(self)
  133. end
  134. end