From: Hugh Sasse Date: 2005-10-21T19:14:12+09:00 Subject: Re: Reflection, observ(er|able) instance vars? On Fri, 21 Oct 2005, Daniel Sheppard wrote: > Problem with the == method you defined is that hash equality != object > equality - especially for your hashing method. Yes, I'd spotted that and was going to take that into account. Thanks > > This module will provide you with the hash and eql? methods (alias those > to other methods as appropriate). The hash function is cached, and reset > whenever a var= method is called (make sure you don't go modifying > hashed vars directly). > > This is probably not the only/best way to do this, but it made sense to > me: > > module FastHashEquals > def attr_hashing( *arr ) > attr_reader *arr > hashers = class_eval "@@__hashers ||= []" > hashers.concat(arr) > arr.each do |var| > define_method(var) { > instance_variable_get("@#{var}") > } > define_method("#{var}=") {|obj| > instance_variable_set("@#{var}", obj) > instance_variable_set(:@__equals_hash, nil) > } > define_method('eql?') { |other| > hash === other.hash && hashers.all? { |x| > send(x) == other.send(x) > } > } > define_method('hash') { > @__equals_hash ||= hashers.inject(0) { |s,x| > s + instance_variable_get("@#{x}").hash > } > } > end > end > end > > To use: > > class HashTest > extend FastHashEquals > attr_hashing :one, :two, :three > end This "delivers us from eval" :-) but does define_method offer anything else over the class_eval %{...} approach? Maybe [only :-)] speed? > Thank you, Hugh