If I absolutely do not want the Hash-like object to have certain hash methods, then I would wrap the object in my own class and only expose the methods I want it to have (your option b).
If I wanted it to maintain its true hash behavior with some added behavior, I would add that behavior in a module to the hash object itself, not modifying the core hash class:
module SpecialHash
def reindex
# method def
end
end
my_hash = {}
my_hash.extend(SpecialHash)
my_hash.reindex #now is defined on my hash
Most commonly, one of these options will do the trick for me.
In general, I tend to favor using modules to extend class behavior instead of class inheritance because I consider it to be a cleaner and more lightweight approach. Creating a new class always gives me the feeling that I am adding a new "thing" to my domain model. This is fine and is exactly what you want to do in countless scenarios, but Ruby's mixin capabilities give you a very nice alternative when you don't actually need to go quite that far.
The main time when I would deal with creating a class is if there is some additional state in the object that I want to keep track of. If my additions are not about expanding on the state of the object, but are just about expanding on it's behavior, then I will almost always start by mixing that behavior into an existing instance of that class using a module.
Another answer to this sort of question also brings up some other points worth keeping in mind as well: ruby inheritance vs mixins