From: Gavin Sinclair Date: 2004-06-18T16:06:32+09:00 Subject: Re: How to make generic #== method? Zakaria wrote: > > I remove the eql? and hash method because > 1) I don't need it You probably need hash, and should define it (see below). About eql?, I'm under the understanding that eql? and == should always return the same thing. > 2) It doesn't work if the class has hash attribute because > {'a' => 1}.hash != {'a' => 1}.hash Now that is weird. I've a faint recollection of it being mentioned on ruby-talk before though, so perhaps its not a bug. > 3) I'm not really understand the functionality to test it > > Could someone enlighten me why Hash#hash doesn't result the same > and where .hash and .eql? used ? #hash is used to generate a hash code, which is used to put an object into a hash (i.e. a Hash object). If two objects have the same #hash value, then a Hash thinks they're probably the same, but it's not guaranteed, so it double-checks with #eql?. However, if two objects have *different* #hash values, then a Hash considers them to be definitely different. Bottom line, if you (re)define #== in an object, you really really should (re)define #hash as well, to make sure they are consistent. > PS: Is there any place where I could post this snippet, > so others could use it? As it happens, I've already written a detailed consideration of Joel's code for the not-yet-formally-announced project 'addlib', so that people can reuse it without having to manage the code themselves. Until then, however, you might take a look at the snippet repository on RubyForge. Joel's code is better, however. What yours adds is the implicit definition of #contents (in Joel's terminology). So why not: module AttrsEquality include ContentEquality def contents res = {} instance_variables.each {|n| res[n.intern] = instance_variable_get(n) } res end end Gavin