Module: Candygram::Wrapper
- Defined in:
- lib/candygram/wrapper.rb
Overview
Utility methods to serialize and unserialize objects into BSON
Constant Summary collapse
- BSON_SAFE =
[String, NilClass, TrueClass, FalseClass, Fixnum, Float, Time, Regexp, ByteBuffer, Mongo::ObjectID, Mongo::Code, Mongo::DBRef]
Class Method Summary collapse
-
.unwrap(thing) ⇒ Object
Undoes any complicated magic from the Wrapper.wrap method.
-
.unwrap_hash(hash) ⇒ Object
Traverses the hash, unwrapping both keys and values.
-
.unwrap_object(hash) ⇒ Object
Turns a hashed object back into an object of the stated class, setting any captured instance variables.
-
.wrap(thing) ⇒ Object
Makes an object safe for the sharp pointy edges of MongoDB.
-
.wrap_array(array) ⇒ Object
Takes an array and returns the same array with unsafe objects wrapped.
-
.wrap_hash(hash) ⇒ Object
Takes a hash and returns it with both keys and values wrapped.
-
.wrap_object(object) ⇒ Object
Returns a nested hash containing the class and instance variables of the object.
-
.wrap_symbol(symbol) ⇒ Object
Returns a string that’s distinctive enough for us to unwrap later and produce the same symbol.
Class Method Details
.unwrap(thing) ⇒ Object
Undoes any complicated magic from the Wrapper.wrap method. Almost everything falls through untouched except for symbol strings and hashed objects.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/candygram/wrapper.rb', line 75 def self.unwrap(thing) case thing when Hash if thing["__object_"] unwrap_object(thing) else unwrap_hash(thing) end when Array thing.map {|element| unwrap(element)} when /^__sym_(.+)/ $1.to_sym else thing end end |
.unwrap_hash(hash) ⇒ Object
Traverses the hash, unwrapping both keys and values. Returns the hash that results.
93 94 95 96 97 |
# File 'lib/candygram/wrapper.rb', line 93 def self.unwrap_hash(hash) unwrapped = {} hash.each {|k,v| unwrapped[unwrap(k)] = unwrap(v)} unwrapped end |
.unwrap_object(hash) ⇒ Object
Turns a hashed object back into an object of the stated class, setting any captured instance variables. The main limitation is that the object’s class must respond to Class.new without any parameters; we will not attempt to guess at any complex initialization behavior.
102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/candygram/wrapper.rb', line 102 def self.unwrap_object(hash) if innards = hash["__object_"] klass = Kernel.const_get(innards["class"]) object = klass.new if innards["ivars"] innards["ivars"].each do |name, value| object.instance_variable_set(name, unwrap(value)) end end object end end |
.wrap(thing) ⇒ Object
Makes an object safe for the sharp pointy edges of MongoDB. Types properly serialized by the BSON.serialize call get passed through unmolested; others are unpacked and their pieces individually shrink-wrapped.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/candygram/wrapper.rb', line 23 def self.wrap(thing) # Pass the simple cases through return thing if BSON_SAFE.include?(thing.class) case thing when Symbol wrap_symbol(thing) when Array wrap_array(thing) when Hash wrap_hash(thing) when Numeric # The most obvious are in BSON_SAFE, but not all thing when Date thing.to_time else wrap_object(thing) # Our catchall machinery end end |
.wrap_array(array) ⇒ Object
Takes an array and returns the same array with unsafe objects wrapped
43 44 45 |
# File 'lib/candygram/wrapper.rb', line 43 def self.wrap_array(array) array.map {|element| wrap(element)} end |
.wrap_hash(hash) ⇒ Object
Takes a hash and returns it with both keys and values wrapped
48 49 50 51 52 |
# File 'lib/candygram/wrapper.rb', line 48 def self.wrap_hash(hash) wrapped = {} hash.each {|k, v| wrapped[wrap(k)] = wrap(v)} wrapped end |
.wrap_object(object) ⇒ Object
Returns a nested hash containing the class and instance variables of the object. It’s not the deepest we could ever go (it doesn’t handle singleton methods, etc.) but it’s a start.
61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/candygram/wrapper.rb', line 61 def self.wrap_object(object) wrapped = {"class" => object.class.name} ivars = {} object.instance_variables.each do |ivar| # Different Ruby versions spit different things out for instance_variables. Annoying. ivar_name = '@' + ivar.to_s.sub(/^@/,'') ivars[ivar_name] = wrap(object.instance_variable_get(ivar_name)) end wrapped["ivars"] = ivars unless ivars.empty? {"__object_" => wrapped} end |
.wrap_symbol(symbol) ⇒ Object
Returns a string that’s distinctive enough for us to unwrap later and produce the same symbol
55 56 57 |
# File 'lib/candygram/wrapper.rb', line 55 def self.wrap_symbol(symbol) "__sym_" + symbol.to_s end |