First, let's be clear about the semantics of the various comparison methods:

The == operator checks whether two objects are equal (after coercing 
them to the same type).

1 == 2 # => false
1 == 1.0 # => true

#eql? checks if two objects are equal and of the same type.

1.eql? 1.0 # => false
'a'.eql? 'a' # => true

#equal? checks if two objects are identical (the same object).

'a'.equal? 'a' # => false
:a.equal? :a # => true

As a mnemonic, note that their strictness is a function of their length.

Now, on to the original question, which (paraphrased) is:

"How can I get arrays of custom objects to work as expected with the 
set intersection operator &?"

The Array#& operator, like its siblings, uses the #hash and #eql? 
methods of the objects it compares. These must be the same for objects 
you want to be considered equivalent.

Armed with this knowledge, let's define those methods on User. For instance:

class User

  # checks if objects are equal
  def ==(other)
    @email == other.email
  end

  # checks if objects are equal and the same class
  def eql?(other)
    self == other && self.class == other.class
  end

  # unique hash based on email and class
  # We add 1 to prevent User.new('').hash == User.hash
  # NOTE: Users with @email == nil will have the same hash and modify 
if necessary.
  def hash
    @email.hash ^ self.class.hash +
  end
end

This will allow:

> [User.new('bob / example.com')] & [User.new('bob / example.com')]
=> [#<User:0x1016dcdb8 @email="bob / example.com">]

Which I believe was the original intent. Keep in mind that this will 
also cause Hash to see them as the same object for keys, which is 
probably also expected

As an aside, I would also like to comment that the following, from one 
of the responses:

 def to_s
  "#@email"
 end

is unnecessarily complex and can be replaced simply with:

def to_s
  @email
end

Don't use string interpolation when you don't need it. If you want to 
ensure that @email is a string, call to_s on it instead.

On 2010-06-03 15:29:55 -0700, Anderson Leite said:
> 
> I need to compare two arrays of users, and get and third array just with
> the matches. I found the "&" method that work for Fixnuns and String,
> but...how to use with objects ?
> 
> 
> class User
>  attr_accessor :email
> end
> 
> a = User.new
> a.email = 'ruby / rails.com'
> 
> b = User.new
> b.email = 'ruby / rails.com'
> 
> array_one = [a]
> array_two = [b]
> 
> 
> array_three = array_one & array_two
> 
> puts array_three # I want the user here
> 
> 
> 
> Can you help me ?
> thanks

Rein Henrichs
http://puppetlabs.com
http://reinh.com