Reputation: 13
I have a hash where multiple keys (lets say 1-5) point to one object (lets call a). Keys (6-10) points to another object(say, b).
At some point I merged "b" into "a", now i have to make sure everyone sees the same object (also merging "a" into "b" and creating two objects with same content is not an option)
Is there a way to make any reference to "b" just redirect to "a" (keys 1-10 now point to object a) without manually updating keys 6-10 ?
Upvotes: 0
Views: 318
Reputation: 198436
You can't switch out one object for another unless you have some kind of a wrapper. Unless performance matters a lot, the easiest wrappers to use are proxy objects, because you don't need to unwrap them: they transparently behave exactly like the wrapped object.
class ProxyObject
# thanks to https://alisdair.mcdiarmid.org/invisible-proxies-with-ruby/
instance_methods.each do |m|
undef_method(m) unless m =~ /(^__|^nil\?$|^send$|^object_id$)/
end
attr_accessor :target
def initialize(target)
@target = target
end
def respond_to?(symbol, include_priv=false)
@target.respond_to?(symbol, include_priv)
end
private def method_missing(method, *args, &block)
@target.send(method, *args, &block)
end
end
a = 1
b = 10
a_proxy = ProxyObject.new(a)
b_proxy = ProxyObject.new(b)
a_proxy.class # verify how well they masquerade
# => Integer
hash = 10.times.map { |i| [i + 1, i < 5 ? a_proxy : b_proxy] }.to_h
# => {1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>10, 7=>10, 8=>10, 9=>10, 10=>10}
hash.values.sum() # confirm it behaves exactly like a number
# => 55
b_proxy.target = a_proxy.target # switch reference
hash
# => {1=>1, 2=>1, 3=>1, 4=>1, 5=>1, 6=>1, 7=>1, 8=>1, 9=>1, 10=>1}
hash.values.sum() # confirm the reference is changed
# => 10
Upvotes: 2
Reputation: 13
I think I found an answer but I still have to code it
instead of the hash having an object, it will contain an array
array[0] will originally point to itself, array[1] will be the actual object
so this is the setup: hash1-5 points to arr1, hash6-10 points to arr2, arr1[0] points to itself and arr1[0]
after merging arr2[1] (b in the original question) into arr1[1] (a into the original question), I will update arr2[0] to point to arr1.
finally, after every key retrieval I will run something along the lines of
test = hash[6]
while test[0] != test
test = test[0]
end
Upvotes: 0