File: equalizer.rb

package info (click to toggle)
ruby-equalizer 0.0.11-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 176 kB
  • sloc: ruby: 356; makefile: 4
file content (121 lines) | stat: -rw-r--r-- 2,685 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# encoding: utf-8

# Define equality, equivalence and inspection methods
class Equalizer < Module
  # Initialize an Equalizer with the given keys
  #
  # Will use the keys with which it is initialized to define #cmp?,
  # #hash, and #inspect
  #
  # @param [Array<Symbol>] keys
  #
  # @return [undefined]
  #
  # @api private
  def initialize(*keys)
    @keys = keys
    define_methods
    freeze
  end

private

  # Hook called when module is included
  #
  # @param [Module] descendant
  #   the module or class including Equalizer
  #
  # @return [self]
  #
  # @api private
  def included(descendant)
    super
    descendant.module_eval { include Methods }
  end

  # Define the equalizer methods based on #keys
  #
  # @return [undefined]
  #
  # @api private
  def define_methods
    define_cmp_method
    define_hash_method
    define_inspect_method
  end

  # Define an #cmp? method based on the instance's values identified by #keys
  #
  # @return [undefined]
  #
  # @api private
  def define_cmp_method
    keys = @keys
    define_method(:cmp?) do |comparator, other|
      keys.all? do |key|
        __send__(key).public_send(comparator, other.__send__(key))
      end
    end
    private :cmp?
  end

  # Define a #hash method based on the instance's values identified by #keys
  #
  # @return [undefined]
  #
  # @api private
  def define_hash_method
    keys = @keys
    define_method(:hash) do | |
      keys.map(&method(:send)).push(self.class).hash
    end
  end

  # Define an inspect method that reports the values of the instance's keys
  #
  # @return [undefined]
  #
  # @api private
  def define_inspect_method
    keys = @keys
    define_method(:inspect) do | |
      klass = self.class
      name  = klass.name || klass.inspect
      "#<#{name}#{keys.map { |key| " #{key}=#{__send__(key).inspect}" }.join}>"
    end
  end

  # The comparison methods
  module Methods
    # Compare the object with other object for equality
    #
    # @example
    #   object.eql?(other)  # => true or false
    #
    # @param [Object] other
    #   the other object to compare with
    #
    # @return [Boolean]
    #
    # @api public
    def eql?(other)
      instance_of?(other.class) && cmp?(__method__, other)
    end

    # Compare the object with other object for equivalency
    #
    # @example
    #   object == other  # => true or false
    #
    # @param [Object] other
    #   the other object to compare with
    #
    # @return [Boolean]
    #
    # @api public
    def ==(other)
      other = coerce(other).first if respond_to?(:coerce, true)
      other.kind_of?(self.class) && cmp?(__method__, other)
    end
  end # module Methods
end # class Equalizer