Class: Aqua::Translator
- Inherits:
-
Object
- Object
- Aqua::Translator
- Defined in:
- lib/aqua/object/translator.rb
Overview
Packing of objects needs to save an object as well as query it. Therefore this packer module gives a lot of class methods and mirrored instance methods that pack various types of objects. The instance methods aggregate all of the attachments and externals that need to be mapped back to the base object after they are saved. The class methods return an array with the packaging in the first element and the attachment and externals in subsequent elements
Defined Under Namespace
Instance Attribute Summary collapse
-
#attachments ⇒ Object
private
An array of attachments that have to be stored by the base object.
-
#base_id ⇒ Object
Returns the value of attribute base_id.
-
#base_object ⇒ Object
Returns the value of attribute base_object.
-
#externals ⇒ Object
private
Hash-like object that gathers all the externally saved aquatic objects.
Class Method Summary collapse
-
.classes ⇒ Object
PACKING ————————————————————————————— ===============================================================================================.
- .get_class(class_str) ⇒ Object
- .new_from_doc(doc, opts) ⇒ Object
-
.pack_ivars(obj, path = '') ⇒ Mash
private
Packs the ivars for a given object.
-
.pack_object(obj, path = '') ⇒ Mash
private
Packs an object into data and meta data.
-
.pack_to_stub(obj, path = '') ⇒ Mash
private
Packs the stub for an externally saved object.
-
.pack_vanilla(obj, path = '') ⇒ Mash
private
Packs the an object requiring no initialization.
- .unpack_ivars(obj, doc, opts) ⇒ Object
- .unpack_object(doc, opts = Opts.new) ⇒ Object
Instance Method Summary collapse
-
#initialize(base_object, base_id = nil) ⇒ Translator
constructor
private
Although most of what the translator does happens via class level methods, instantiation happens to maintain a reference to the base object when packing/saving externals and attachments.
-
#load_base(base_object, base_id = nil) ⇒ Object
Method used by initialized and reload_object to set necessary base object data.
-
#pack ⇒ Object
private
This is a wrapper method that takes the a class method and aggregates externals and attachments.
-
#pack_ivars(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method.
-
#pack_object(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method.
-
#pack_to_stub(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method.
-
#pack_vanilla(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method.
- #reload_from_init(doc) ⇒ Object
- #reload_object(obj, doc) ⇒ Object
- #unpack_ivars(doc) ⇒ Object
- #unpack_object(doc, opts = Opts.new) ⇒ Object
Constructor Details
#initialize(base_object, base_id = nil) ⇒ Translator
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Although most of what the translator does happens via class level methods, instantiation happens to maintain a reference to the base object when packing/saving externals and attachments. It is also needed in the unpack process to locate attachments.
36 37 38 |
# File 'lib/aqua/object/translator.rb', line 36 def initialize( base_object, base_id=nil ) load_base( base_object, base_id ) end |
Instance Attribute Details
#attachments ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
An array of attachments that have to be stored by the base object
25 26 27 |
# File 'lib/aqua/object/translator.rb', line 25 def @attachments ||= [] end |
#base_id ⇒ Object
Returns the value of attribute base_id.
8 9 10 |
# File 'lib/aqua/object/translator.rb', line 8 def base_id @base_id end |
#base_object ⇒ Object
Returns the value of attribute base_object.
8 9 10 |
# File 'lib/aqua/object/translator.rb', line 8 def base_object @base_object end |
#externals ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Hash-like object that gathers all the externally saved aquatic objects. Pattern for storage is
external_object => 'pack_path_to_object'
where the string ‘pack_path_to_object’ gets instance evaled in order to update the id in the pack after a new external is saved
19 20 21 |
# File 'lib/aqua/object/translator.rb', line 19 def externals @externals ||= {} end |
Class Method Details
.classes ⇒ Object
PACKING —————————————————————————————
226 227 228 |
# File 'lib/aqua/object/translator.rb', line 226 def self.classes @classes ||= {} end |
.get_class(class_str) ⇒ Object
230 231 232 |
# File 'lib/aqua/object/translator.rb', line 230 def self.get_class( class_str ) classes[class_str] ||= class_str.constantize if class_str end |
.new_from_doc(doc, opts) ⇒ Object
257 258 259 260 261 262 263 264 |
# File 'lib/aqua/object/translator.rb', line 257 def self.new_from_doc( doc, opts ) klass = get_class( doc['class'] ) obj = if (init = doc['init']) && klass.respond_to?( :aqua_init ) klass.aqua_init( init, opts ) else klass.new end end |
.pack_ivars(obj, path = '') ⇒ Mash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Packs the ivars for a given object.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/aqua/object/translator.rb', line 62 def self.pack_ivars( obj, path='' ) path = "#{path}['ivars']" rat = Rat.new vars = obj.respond_to?(:_storable_attributes) ? obj._storable_attributes : obj.instance_variables vars.each do |ivar_name| ivar = obj.instance_variable_get( ivar_name ) ivar_path = path + "['#{ivar_name}']" if ivar if ivar == obj # self referential TODO: this will only work direct descendants :( ivar_rat = pack_to_stub( ivar, ivar_path ) rat.hord( ivar_rat, ivar_name ) else ivar_rat = pack_object( ivar, ivar_path ) rat.hord( ivar_rat, ivar_name ) end end end rat end |
.pack_object(obj, path = '') ⇒ Mash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Packs an object into data and meta data. Works recursively sending out to array, hash, etc.
object packers, which send their values back to _pack_object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/aqua/object/translator.rb', line 95 def self.pack_object( obj, path='' ) klass = obj.class if obj.respond_to?(:to_aqua) # probably requires special initialization not just ivar assignment obj.to_aqua( path ) elsif obj.aquatic? if obj. || path == '' pack_vanilla( obj, path ) else pack_to_stub( obj, path) end else pack_vanilla( obj, path ) end end |
.pack_to_stub(obj, path = '') ⇒ Mash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Packs the stub for an externally saved object.
141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/aqua/object/translator.rb', line 141 def self.pack_to_stub( obj, path='' ) rat = Rat.new( {'class' => 'Aqua::Stub'} ) stub_rat = Rat.new({'class' => obj.class.to_s, 'id' => obj.id || '' }, {obj => path} ) # deal with cached methods unless (stub_methods = obj._stubbed_methods).empty? stub_rat.pack['methods'] = {} stub_methods.each do |meth| meth = meth.to_s method_rat = pack_object( obj.send( meth ) ) stub_rat.hord( method_rat, ['methods', "#{meth}"]) end end rat.hord( stub_rat, 'init' ) end |
.pack_vanilla(obj, path = '') ⇒ Mash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Packs the an object requiring no initialization.
121 122 123 124 125 126 |
# File 'lib/aqua/object/translator.rb', line 121 def self.pack_vanilla( obj, path='' ) rat = Rat.new( { 'class' => obj.class.to_s } ) ivar_rat = pack_ivars( obj, path ) rat.hord( ivar_rat, 'ivars' ) unless ivar_rat.pack.empty? rat end |
.unpack_ivars(obj, doc, opts) ⇒ Object
283 284 285 286 287 288 289 290 291 292 |
# File 'lib/aqua/object/translator.rb', line 283 def self.unpack_ivars( obj, doc, opts ) # add the ivars if ivars = doc['ivars'] ivars.each do |ivar_name, ivar_hash| opts.path += "#{ivar_name}" unpacked_ivar = unpack_object( ivar_hash, opts ) obj.instance_variable_set( ivar_name, unpacked_ivar ) end end end |
.unpack_object(doc, opts = Opts.new) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/aqua/object/translator.rb', line 240 def self.unpack_object( doc, opts=Opts.new ) if doc.respond_to?(:from_aqua) doc.from_aqua # these are basic types, like nil, strings, true/false, or symbols else obj = new_from_doc( doc, opts ) # mixin the id and rev if obj.aquatic? && !obj. obj.id = doc.id if doc.id obj._rev = doc.rev if doc.rev end unpack_ivars( obj, doc, opts ) obj end end |
Instance Method Details
#load_base(base_object, base_id = nil) ⇒ Object
Method used by initialized and reload_object to set necessary base object data
41 42 43 44 |
# File 'lib/aqua/object/translator.rb', line 41 def load_base( base_object, base_id=nil) self.base_object = base_object self.base_id = base_object.id || base_id end |
#pack ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This is a wrapper method that takes the a class method and aggregates externals and attachments
48 49 50 51 52 53 |
# File 'lib/aqua/object/translator.rb', line 48 def pack rat = yield self.externals.merge!( rat.externals ) self. += rat. rat.pack end |
#pack_ivars(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method. It otherwise performs the class method
83 84 85 |
# File 'lib/aqua/object/translator.rb', line 83 def pack_ivars( obj, path='' ) pack { self.class.pack_ivars( obj ) } end |
#pack_object(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method. It otherwise performs the class method
111 112 113 |
# File 'lib/aqua/object/translator.rb', line 111 def pack_object( obj, path='' ) pack { self.class.pack_object( obj ) } end |
#pack_to_stub(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method. It otherwise performs the class method
157 158 159 |
# File 'lib/aqua/object/translator.rb', line 157 def pack_to_stub( obj, path='' ) pack { self.class.pack_to_stub( obj ) } end |
#pack_vanilla(obj, path = '') ⇒ Object
The instance version is wrapped by the #pack method. It otherwise performs the class method
129 130 131 |
# File 'lib/aqua/object/translator.rb', line 129 def pack_vanilla( obj, path='' ) pack { self.class.pack_vanilla( obj ) } end |
#reload_from_init(doc) ⇒ Object
266 267 268 269 270 271 272 273 |
# File 'lib/aqua/object/translator.rb', line 266 def reload_from_init( doc ) if init = doc['init'] raise NotImplementedError, "Class #{base_object.class} does not implement a #replace method and can't be reloaded" unless base_object.respond_to?( :replace ) init_unpacked = unpack_object( {'class' => init.class.to_s, 'init' => init } ) base_object.replace( init_unpacked ) end base_object end |
#reload_object(obj, doc) ⇒ Object
294 295 296 297 298 299 300 |
# File 'lib/aqua/object/translator.rb', line 294 def reload_object( obj, doc ) load_base( obj ) # loads this object as the base for the translator reload_from_init( doc ) # todo: clear all non-hidden ivars too unpack_ivars( doc ) base_object._rev = doc.rev if doc.rev end |
#unpack_ivars(doc) ⇒ Object
275 276 277 278 279 280 |
# File 'lib/aqua/object/translator.rb', line 275 def unpack_ivars( doc ) opts = Opts.new opts.base_object = self.base_object opts.base_id = self.base_object.id || self.base_id self.class.unpack_ivars( base_object, doc, opts ) end |
#unpack_object(doc, opts = Opts.new) ⇒ Object
234 235 236 237 238 |
# File 'lib/aqua/object/translator.rb', line 234 def unpack_object( doc, opts=Opts.new ) opts.base_object = self.base_object opts.base_id = self.base_object.id || self.base_id self.class.unpack_object( doc, opts ) end |