I want to override the Hash class native brackets in ruby.
Note I don't want to override them in a class that inherits from Hash (no subclassing), I want to actually override Hash itself, such that any hash anywhere will always inherit my behavior.
Specifically (bonus points for..) - I want this in order to natively emulate a hash with indifferent access. In JavaScript I would modify the prototype
, Ruby is known for its metaprogramming, so I hope this is possible.
So what I am aiming for is:
>> # what do I do here to overload Hash's []?...
>> x = {a:123} # x is a native Hash
>> x[:a] # == 123, as usual
>> x['a'] # == 123, hooray!
I've tried: 1)
class Hash
define_method(:[]) { |other| puts "Hi, "; puts other }
end
and
class Hash
def []
puts 'bar'
end
end
Both crash irb.
This seems to get the job done.
class Hash
def [](key)
value = (fetch key, nil) || (fetch key.to_s, nil) || (fetch key.to_sym, nil)
end
def []=(key,val)
if (key.is_a? String) || (key.is_a? Symbol) #clear if setting str/sym
self.delete key.to_sym
self.delete key.to_s
end
merge!({key => val})
end
end
And now:
user = {name: 'Joe', 'age' => 20} #literal hash with both symbols and strings as keys
user['name'] == 'Joe' # cool!
user[:age] == 20 # cool!
For more details see: http://www.sellarafaeli.com/blog/ruby_monkeypatching_friendly_hashes
class Hash
def [] key
value = fetch key rescue
case key
when Symbol then "#{value}, as usual"
when String then "#{value}, hooray!"
else value end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With