Created
May 28, 2010 08:51
-
-
Save rklemme/416922 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This class works as a proxy for an instance | |
| # and presents it as Hash. | |
| class InstanceHash | |
| include Enumerable | |
| def initialize(obj, default_val = nil, &default_proc) | |
| @obj = obj | |
| @default = default_val | |
| @default_proc = default_proc || lambda {|h,k| @default} | |
| end | |
| def size | |
| keys.size | |
| end | |
| def empty? | |
| keys.empty? | |
| end | |
| def keys | |
| @obj.instance_variables | |
| end | |
| def values | |
| keys.map {|iv| get_val(iv)} | |
| end | |
| def has_key? k | |
| check_key(normalize(k)) | |
| end | |
| alias key? has_key? | |
| def has_value? v | |
| keys.any? {|iv| v.eql? get_val(iv)} | |
| end | |
| alias value? has_value? | |
| def each_pair | |
| keys.each do |iv| | |
| yield iv, get_val(iv) | |
| end | |
| self | |
| end | |
| alias each each_pair | |
| def each_key(&b) | |
| keys.each(&b) | |
| self | |
| end | |
| def each_value | |
| keys.each do |iv| | |
| yield get_val(iv) | |
| end | |
| self | |
| end | |
| def fetch(key, &fallback) | |
| iv = normalize(key) | |
| if check_key(iv) | |
| get_val(iv) | |
| elsif fallback | |
| fallback[iv] | |
| else | |
| raise KeyError, 'key not found' | |
| end | |
| end | |
| def [] key | |
| fetch key do |iv| | |
| @default_proc[self, iv] | |
| end | |
| end | |
| def []= key, val | |
| @obj.instance_variable_set(normalize(key), val) | |
| end | |
| def assoc key | |
| iv = normalize(key) | |
| check_key(iv) && [iv, get_val(iv)] | |
| end | |
| def rassoc val | |
| each_pair do |iv, v| | |
| return [iv, v] if val.eql? v | |
| end | |
| nil | |
| end | |
| private | |
| # check a key | |
| # iv must be normalized | |
| def check_key(iv) | |
| @obj.instance_variable_defined? iv | |
| end | |
| # get a value | |
| # iv must be normalized | |
| def get_val(iv) | |
| @obj.instance_variable_get(iv) | |
| end | |
| # Convert a String or Symbol into a proper | |
| # ivar name | |
| def normalize(var_name) | |
| case var_name | |
| when /\A@/ # covers String and Symbol | |
| var_name | |
| when String,Symbol | |
| :"@#{var_name}" | |
| else | |
| raise ArgumentError, "Not a valid instance variable key: %p" % var_name | |
| end | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment