I'm looking for a kind of "append-only" hash where keys may only be set once.
For example:
capitals = AppendOnlyHash.new
capitals['france'] = 'paris'
capitals['japan'] = 'tokyo'
capitals['france'] = 'nice' # raises immutable exception
Any library recommendations or ideas how to achieve this?
(Use case is a logging type object which will be passed to numerouis loosely connected classes, and wanting to detect if any use the same key.)
There are 10 methods, directly mutating the hash:
Hash.instance_methods.grep(/.+!\z/) << %i|[]= delete keep_if|
#⇒ [:select!, :filter!, :reject!, :compact!, delete, keep_if,
# :transform_keys!, :transform_values!, :merge!, :[]=]
Also, there is a possibility to mutate values themselves (capitals['france'] << ' and Lyon'
,) so we are to prevent this as well.
class MyHash < Hash; end
MyHash.prepend(
Module.new do
(Hash.instance_methods.grep(/.+!\z/) | %i|delete keep_if|).each do |method|
define_method(method) do |*args|
raise "Method #{method} is restricted since it is mutating"
end
end
def []=(key, val)
raise "This hash is immutable" if key?(key)
super(key, val.freeze) # to prevent inplace mutations
end
end
)
One needs to derive from Hash
because otherwise we are to break all the hashes.
I did not test this code but it should work out of the box, (if not, the idea should be clear.)