[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Overriding eql? and hash

César Díaz

4/26/2009 10:06:00 AM

Hi,

I am working in an application and I need to store my own objects in
some collections. I was using instances of Array to store that objects,
but now, I need not to store duplicated instances. Searching the Web I
found de class 'Set', which seems to do that. I also read that with this
collection you have to override the eql? and hash methods in your
classes objects to set a criteria to compare you objects.

I will try to explain better myself with an example:

I have the following class Track

class Track < ActiveRecord::Base
belongs_to :album

def hash
StringUtils.nice_slug(self.name, "false").hash

end

def eql?(other)
equal = false
if StringUtils.nice_slug(self.name, "false").downcase.eql?
StringUtils.nice_slug(other.name, "false").downcase
equal = true
end
equal
end
end

Now, I create two instances of Track and two of Set, and I insert one
track into each Set.

a = Set::new

t1 = Track.new

=> #<Track id: nil, name: nil, lyric: nil, created_at: nil, updated_at:
nil>

t1.name = "Gracias por elegirme"

t2 = Track.new

=> #<Track id: nil, name: nil, lyric: nil, created_at: nil, updated_at:
nil>

t2.name = "Gracias Por Elegirme"

a << t1

=> #<Set: {#<Track id: nil, name: "Gracias por elegirme", lyric: nil,
created_at: nil, updated_at: nil>}>

b = Set::new

b << t2

#<Set: {#<Track id: nil, name: "Gracias Por Elegirme", lyric: nil,
created_at: nil, updated_at: nil>}>

And finally, I try to insert the content of b into a:

a.merge(b)

The result that I am expecting is that nothing is inserted into a
because the name of the two tracks is very similar, and when we convert
into downcase the are equal ("gracias por elegirme").

But instead I get the following:

#<Set: {#<Track id: nil, name: "Gracias Por Elegirme", lyric: nil,
created_at: nil, updated_at: nil>, #<Track id: nil, name: "Gracias por
elegirme", lyric: nil, created_at: nil, updated_at: nil>}>

Now a stores the two Track instances.

I would appreciate so much your help.
--
Posted via http://www.ruby-....

2 Answers

Sebastian Hungerecker

4/26/2009 11:38:00 AM

0

C=C3=A9sar D=C3=ADaz wrote:
> def hash
> =C2=A0 =C2=A0 StringUtils.nice_slug(self.name, "false").hash
>
> =C2=A0 end
>
> =C2=A0 def eql?(other)
> =C2=A0 =C2=A0 equal =3D false
> =C2=A0 =C2=A0 if StringUtils.nice_slug(self.name, "false").downcase.eql?
> StringUtils.nice_slug(other.name, "false").downcase
> =C2=A0 =C2=A0 =C2=A0 equal =3D true
> =C2=A0 =C2=A0 end
> =C2=A0 =C2=A0 equal
> =C2=A0 end

If two strings are equal except for case your eql? method will return true.=
Or=20
at least it would if it ever got called. But since you don't call downcase =
in=20
the hash method, those two objects will have different hash values and Set=
=20
will never bother to call eql? on them.
In other words: call downcase in the hash method as well and you'll be fine.

HTH,
Sebastian

César Díaz

4/26/2009 2:54:00 PM

0

It works perfectly.

Thank you very much!!!
--
Posted via http://www.ruby-....