All Objects Are Created .equal?
  Understand equality in your Ruby codez
github.com/gsterndale/equality
Equality methods


a == b

a === b

a.eql? b

a.equal? b
==
Everyday equality (==)



a == b
Default ==

a = MyBasicClass.new
b = MyBasicClass.new

a == b
# => false

b = a

a == b
# => true
Overriding ==
class RomanNumeral

  def ==(other)
    if other.respond_to?(:to_f)
      self.to_f == other.to_f
    else
      false
    end
  end

end
Overriding ==


iv   = RomanNumeral.new('IV')

iiii = RomanNumeral.new('IIII')

iv == iiii
# => true
===
case statement equality (===)



a === b
Default ===

a = Object.new
b = Object.new

case   a
when   b
  'b   must === a'
else
  'b   must NOT === a'
end
# =>   "b must NOT === a"
Float ===

a = 1
b = 1.0

case   a
when   b
  'b   must === a'
else
  'b   must NOT === a'
end
# =>   "b must === a"
Regexp ===


case '123'
when /d+/
  'At least one number'
else
  'No numbers found'
end
# => "At least one number"
When === != ==


/d+/ == '123'
# => false

/d+/ === '123'
# => true
Class ===


case 'abc'
when String
  'It is a String!'
else
  'Not a String'
end
# => "It is a String!"
Asymmetry


/d+/ === '123'
# => true

'123' === /d+/
# => false
Asymmetry

2 === Integer
# => false

Integer === 2
# => true

Fixnum === 2
# => true
.equal?
Object equality (.equal?)

a = 'FOO'
b = a

a.equal? b
# => true

a.equal? 'FOO'
# => false
.eql?
Hash key equality (.eql?)



a.eql? b
Default .eql?
foo = Object.new
hash = { foo => 'My value' }

bar = Object.new

foo.equal? bar
# => false
foo.eql? bar
# => false

hash[bar]
# => nil
String .eql?
foo = 'My Key'
hash = { foo => 'My value' }

bar = 'My Key'

foo.equal? bar
# => false
foo.eql? bar
# => true

hash[bar]
# => "My value"
Overriding .eql?

class RomanNumeral

  def eql?(other)
    other.kind_of?(RomanNumeral) &&
      self.to_i.eql?(other.to_i)
  end

end
Overriding .eql?
iv   = RomanNumeral.new('IV')

hash = { iv => 'Four' }

iiii = RomanNumeral.new('IIII')

iv.equal? iiii
# => false
iv.eql? iiii
# => true

hash[iiii]
# => "Four"
Comparable
Comparison methods
# You must define <=>
a <=> b
# => -1, 0, 1 -or- nil

a == b

a   > b
a   < b
a   >= b
a   <= b

c.between?(a, b)
Overriding <=>
class RomanNumeral

  def <=>(other)
    if other.respond_to?(:to_f)
      self.to_f <=> other.to_f
    else
      nil
    end
  end

end
Overriding <=>
v = RomanNumeral.new('V')
x = RomanNumeral.new('X')

v <=> x
# => -1

v >= x
# => false

RomanNumeral.new('VIII').between?(v, x)
# => true
Sorting Enumerables

iv   = RomanNumeral.new('IV')
iiii = RomanNumeral.new('IIII')
x    = RomanNumeral.new('X')

[iv, x, iiii]
# => [IV, X, IIII]

[iv, x, iiii].sort
# => [IV, IIII, X]