equatable 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Equatable
2
- [![Build Status](https://secure.travis-ci.org/peter-murach/equatable.png?branch=master)][travis] [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
2
+ [![Gem Version](https://badge.fury.io/rb/equatable.png)](http://badge.fury.io/rb/equatable) [![Build Status](https://secure.travis-ci.org/peter-murach/equatable.png?branch=master)][travis] [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
3
3
 
4
4
  [travis]: http://travis-ci.org/peter-murach/equatable
5
5
  [codeclimate]: https://codeclimate.com/github/peter-murach/equatable
@@ -51,7 +51,9 @@ It is assumed that your objects are value objects and the only values that affec
51
51
 
52
52
  ```
53
53
 
54
- It is important that the attribute readers should allow for performing deterministic computations on class instances.
54
+ It is important that the attribute readers should allow for performing deterministic computations on class instances. Therefore you should avoid specifying attributes that depend on unreliable resources like IP address that require network access.
55
+
56
+ Note that adding a extra attr reader to a subclass will violate the equivalence contract.
55
57
 
56
58
  ## Contributing
57
59
 
@@ -130,7 +130,7 @@ module Equatable
130
130
  #
131
131
  # @api public
132
132
  def eql?(other)
133
- instance_of?(other.class) and compare?(__method__, other)
133
+ instance_of?(other.class) && compare?(__method__, other)
134
134
  end
135
135
 
136
136
  # Compare two objects for equality based on their value
@@ -143,8 +143,7 @@ module Equatable
143
143
  #
144
144
  # @api public
145
145
  def ==(other)
146
- return false unless self.class <=> other.class
147
- compare?(__method__, other)
146
+ kind_of?(other.class) && compare?(__method__, other)
148
147
  end
149
148
 
150
149
  end # Methods
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  module Equatable
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -2,205 +2,53 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Equatable do
5
+ describe Equatable, '#eql?' do
6
6
  let(:name) { 'Value' }
7
+ let(:value) { 11 }
7
8
 
8
- context 'without attributes' do
9
- let(:klass) { ::Class.new }
9
+ let(:klass) {
10
+ ::Class.new do
11
+ include Equatable
10
12
 
11
- subject { klass.new }
13
+ attr_reader :value
12
14
 
13
- before {
14
- klass.stub(:name).and_return 'Value'
15
- klass.send :include, described_class
16
- }
17
-
18
- it { should respond_to :compare? }
19
-
20
- it { should be_instance_of klass }
21
-
22
- describe '#eql?' do
23
- context 'when objects are similar' do
24
- let(:other) { subject.dup }
25
-
26
- it { subject.eql?(other).should be_true }
27
- end
28
-
29
- context 'when objects are different' do
30
- let(:other) { stub('other') }
31
-
32
- it { subject.eql?(other).should be_false }
15
+ def initialize(value)
16
+ @value = value
33
17
  end
34
18
  end
19
+ }
35
20
 
36
- describe '#==' do
37
- context 'when objects are similar' do
38
- let(:other) { subject.dup }
39
-
40
- it { (subject == other).should be_true }
41
- end
21
+ let(:object) { klass.new(value) }
42
22
 
43
- context 'when objects are different' do
44
- let(:other) { stub('other') }
23
+ subject { object.eql?(other) }
45
24
 
46
- it { (subject == other)}
47
- end
48
- end
25
+ context 'with the same object' do
26
+ let(:other) { object }
49
27
 
50
- describe '#inspect' do
51
- it { subject.inspect.should eql('#<Value>') }
52
- end
28
+ it { should be_true }
53
29
 
54
- describe '#hash' do
55
- it { subject.hash.should eql([klass].hash) }
30
+ it 'is symmetric' do
31
+ should eql(other.eql?(object))
56
32
  end
57
-
58
-
59
33
  end
60
34
 
61
- context 'with attributes' do
62
- let(:value) { 11 }
63
- let(:klass) {
64
- ::Class.new do
65
- include Equatable
66
-
67
- attr_reader :value
68
-
69
- def initialize(value)
70
- @value = value
71
- end
72
- end
73
- }
74
-
75
- before {
76
- klass.stub(:name).and_return name
77
- }
78
-
79
- subject { klass.new(value) }
80
-
81
- it 'dynamically defines #hash method' do
82
- klass.method_defined?(:hash).should be_true
83
- end
84
-
85
- it 'dynamically defines #inspect method' do
86
- klass.method_defined?(:inspect).should be_true
87
- end
88
-
89
- it { should respond_to :compare? }
90
-
91
- it { should respond_to :eql? }
92
-
93
- describe '#eql?' do
94
- context 'when objects are similar' do
95
- let(:other) { subject.dup }
96
-
97
- it { subject.eql?(other).should be_true }
98
- end
99
-
100
- context 'when objects are different' do
101
- let(:other) { stub('other') }
102
-
103
- it { subject.eql?(other).should be_false }
104
- end
105
- end
106
-
107
- describe '#==' do
108
- context 'when objects are similar' do
109
- let(:other) { subject.dup }
110
-
111
- it { (subject == other).should be_true }
112
- end
113
-
114
- context 'when objects are different' do
115
- let(:other) { stub('other') }
116
-
117
- it { (subject == other).should be_false }
118
- end
119
- end
120
-
121
- describe '#inspect' do
122
- it { subject.inspect.should eql('#<Value value=11>') }
123
- end
124
-
125
- describe '#hash' do
126
- it { subject.hash.should eql( ([klass] + [value]).hash) }
127
- end
128
-
129
- context 'equivalence relation' do
130
- let(:other) { subject.dup }
35
+ context 'with an equivalent object' do
36
+ let(:other) { object.dup }
131
37
 
132
- it 'is not equal to nil reference' do
133
- subject.eql?(nil).should be_false
134
- end
135
-
136
- it 'is reflexive' do
137
- subject.eql?(subject).should be_true
138
- end
139
-
140
- it 'is symmetric' do
141
- (subject.eql?(other)).should eql( other.eql?(subject) )
142
- end
38
+ it { should be_true }
143
39
 
144
- it 'is transitive'
40
+ it 'is symmetric' do
41
+ should eql(other.eql?(object))
145
42
  end
146
43
  end
147
44
 
148
- context 'subclass' do
149
- let(:value) { 11 }
150
- let(:klass) {
151
- ::Class.new do
152
- include Equatable
153
-
154
- attr_reader :value
155
-
156
- def initialize(value)
157
- @value = value
158
- end
159
- end
160
- }
161
- let(:subclass) { ::Class.new(klass) }
162
-
163
- before {
164
- klass.stub(:name).and_return name
165
- }
45
+ context 'with an equivalent object of a subclass' do
46
+ let(:other) { ::Class.new(klass).new(value) }
166
47
 
167
- subject { subclass.new(value) }
48
+ it { should be_false }
168
49
 
169
- it { subclass.superclass.should == klass }
170
-
171
- it { should respond_to :value }
172
-
173
- describe '#inspect' do
174
- it { subject.inspect.should eql('#<Value value=11>') }
175
- end
176
-
177
- describe '#eql?' do
178
- context 'when objects are similar' do
179
- let(:other) { subject.dup }
180
-
181
- it { subject.eql?(other).should be_true }
182
- end
183
-
184
- context 'when objects are different' do
185
- let(:other) { stub('other') }
186
-
187
- it { subject.eql?(other).should be_false }
188
- end
189
- end
190
-
191
- describe '#==' do
192
- context 'when objects are similar' do
193
- let(:other) { subject.dup }
194
-
195
- it { (subject == other).should be_true }
196
- end
197
-
198
- context 'when objects are different' do
199
- let(:other) { stub('other') }
200
-
201
- it { (subject == other)}
202
- end
50
+ it 'is symmetric' do
51
+ should eql(other.eql?(object))
203
52
  end
204
53
  end
205
-
206
54
  end
@@ -0,0 +1,76 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Equatable, '#==' do
6
+ let(:name) { 'Value' }
7
+ let(:value) { 11 }
8
+
9
+ let(:super_klass) {
10
+ ::Class.new do
11
+ include Equatable
12
+
13
+ attr_reader :value
14
+
15
+ def initialize(value)
16
+ @value = value
17
+ end
18
+ end
19
+ }
20
+
21
+ let(:klass) { Class.new(super_klass) }
22
+
23
+ let(:object) { klass.new(value) }
24
+
25
+ subject { object == other }
26
+
27
+ context 'with the same object' do
28
+ let(:other) { object }
29
+
30
+ it { should be_true }
31
+
32
+ it 'is symmetric' do
33
+ should eql(other == object)
34
+ end
35
+ end
36
+
37
+ context 'with an equivalent object' do
38
+ let(:other) { object.dup }
39
+
40
+ it { should be_true }
41
+
42
+ it 'is symmetric' do
43
+ should eql(other == object)
44
+ end
45
+ end
46
+
47
+ context 'with an equivalent object of a subclass' do
48
+ let(:other) { ::Class.new(klass).new(value) }
49
+
50
+ it { should be_false }
51
+
52
+ it 'is not symmetric' do
53
+ should_not eql(other == object)
54
+ end
55
+ end
56
+
57
+ context 'with an equivalent object of a superclass' do
58
+ let(:other) { super_klass.new(value) }
59
+
60
+ it { should be_true }
61
+
62
+ it 'is not symmetric' do
63
+ should_not eql(other == object)
64
+ end
65
+ end
66
+
67
+ context 'with an object of another class' do
68
+ let(:other) { Class.new.new }
69
+
70
+ it { should be_false }
71
+
72
+ it 'is symmetric' do
73
+ should eql(other == object)
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,170 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Equatable, '#include' do
6
+ let(:name) { 'Value' }
7
+ let(:object) { described_class }
8
+
9
+ context 'without attributes' do
10
+ let(:klass) { ::Class.new }
11
+
12
+ subject { klass.new }
13
+
14
+ before {
15
+ klass.stub(:name).and_return name
16
+ klass.send(:include, object)
17
+ }
18
+
19
+ it { should respond_to :compare? }
20
+
21
+ it { should be_instance_of klass }
22
+
23
+ describe '#inspect' do
24
+ it { subject.inspect.should eql('#<Value>') }
25
+ end
26
+
27
+ describe '#hash' do
28
+ it { subject.hash.should eql([klass].hash) }
29
+ end
30
+
31
+ describe '#eql?' do
32
+ context 'when objects are similar' do
33
+ let(:other) { subject.dup }
34
+
35
+ it { subject.eql?(other).should be_true }
36
+ end
37
+
38
+ context 'when objects are different' do
39
+ let(:other) { stub('other') }
40
+
41
+ it { subject.eql?(other).should be_false }
42
+ end
43
+ end
44
+
45
+ describe '#==' do
46
+ context 'when objects are similar' do
47
+ let(:other) { subject.dup }
48
+
49
+ it { (subject == other).should be_true }
50
+ end
51
+
52
+ context 'when objects are different' do
53
+ let(:other) { stub('other') }
54
+
55
+ it { (subject == other)}
56
+ end
57
+ end
58
+
59
+ context 'equivalence relation' do
60
+ let(:other) { subject.dup }
61
+ let(:another) { other.dup }
62
+
63
+ it 'is not equal to nil reference' do
64
+ expect(subject.eql?(nil)).to be_false
65
+ end
66
+
67
+ it 'is reflexive' do
68
+ expect(subject.eql?(subject)).to be_true
69
+ end
70
+
71
+ it 'is symmetric' do
72
+ expect(subject.eql?(other)).to eql( other.eql?(subject) )
73
+ end
74
+
75
+ it 'is transitive' do
76
+ expect(subject.eql?(other) && other.eql?(another)).to eql(subject.eql?(another))
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'with attributes' do
82
+ let(:value) { 11 }
83
+ let(:klass) {
84
+ ::Class.new do
85
+ include Equatable
86
+
87
+ attr_reader :value
88
+
89
+ def initialize(value)
90
+ @value = value
91
+ end
92
+ end
93
+ }
94
+
95
+ before {
96
+ klass.stub(:name).and_return name
97
+ }
98
+
99
+ subject { klass.new(value) }
100
+
101
+ it 'dynamically defines #hash method' do
102
+ klass.method_defined?(:hash).should be_true
103
+ end
104
+
105
+ it 'dynamically defines #inspect method' do
106
+ klass.method_defined?(:inspect).should be_true
107
+ end
108
+
109
+ it { should respond_to :compare? }
110
+
111
+ it { should respond_to :eql? }
112
+
113
+ describe '#eql?' do
114
+ context 'when objects are similar' do
115
+ let(:other) { subject.dup }
116
+
117
+ it { subject.eql?(other).should be_true }
118
+ end
119
+
120
+ context 'when objects are different' do
121
+ let(:other) { stub('other') }
122
+
123
+ it { subject.eql?(other).should be_false }
124
+ end
125
+ end
126
+
127
+ describe '#==' do
128
+ context 'when objects are similar' do
129
+ let(:other) { subject.dup }
130
+
131
+ it { (subject == other).should be_true }
132
+ end
133
+
134
+ context 'when objects are different' do
135
+ let(:other) { stub('other') }
136
+
137
+ it { (subject == other).should be_false }
138
+ end
139
+ end
140
+
141
+ describe '#inspect' do
142
+ it { subject.inspect.should eql('#<Value value=11>') }
143
+ end
144
+
145
+ describe '#hash' do
146
+ it { subject.hash.should eql( ([klass] + [value]).hash) }
147
+ end
148
+
149
+ context 'equivalence relation' do
150
+ let(:other) { subject.dup }
151
+ let(:another) { other.dup }
152
+
153
+ it 'is not equal to nil reference' do
154
+ expect(subject.eql?(nil)).to be_false
155
+ end
156
+
157
+ it 'is reflexive' do
158
+ expect(subject.eql?(subject)).to be_true
159
+ end
160
+
161
+ it 'is symmetric' do
162
+ expect(subject.eql?(other)).to eql( other.eql?(subject) )
163
+ end
164
+
165
+ it 'is transitive' do
166
+ expect(subject.eql?(other) && other.eql?(another)).to eql(subject.eql?(another))
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,66 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Equatable, 'subclass' do
6
+ let(:name) { 'Value' }
7
+
8
+ context 'when subclass' do
9
+ let(:value) { 11 }
10
+ let(:klass) {
11
+ ::Class.new do
12
+ include Equatable
13
+
14
+ attr_reader :value
15
+
16
+ def initialize(value)
17
+ @value = value
18
+ end
19
+ end
20
+ }
21
+ let(:subclass) { ::Class.new(klass) }
22
+
23
+ before {
24
+ klass.stub(:name).and_return name
25
+ }
26
+
27
+ subject { subclass.new(value) }
28
+
29
+ it { subclass.superclass.should == klass }
30
+
31
+ it { should respond_to :value }
32
+
33
+ describe '#inspect' do
34
+ it { subject.inspect.should eql('#<Value value=11>') }
35
+ end
36
+
37
+ describe '#eql?' do
38
+ context 'when objects are similar' do
39
+ let(:other) { subject.dup }
40
+
41
+ it { subject.eql?(other).should be_true }
42
+ end
43
+
44
+ context 'when objects are different' do
45
+ let(:other) { stub('other') }
46
+
47
+ it { subject.eql?(other).should be_false }
48
+ end
49
+ end
50
+
51
+ describe '#==' do
52
+ context 'when objects are similar' do
53
+ let(:other) { subject.dup }
54
+
55
+ it { (subject == other).should be_true }
56
+ end
57
+
58
+ context 'when objects are different' do
59
+ let(:other) { stub('other') }
60
+
61
+ it { (subject == other)}
62
+ end
63
+ end
64
+ end
65
+
66
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: equatable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-28 00:00:00.000000000 Z
12
+ date: 2013-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2160246200 !ruby/object:Gem::Requirement
16
+ requirement: &2160139560 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2160246200
24
+ version_requirements: *2160139560
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &2160245720 !ruby/object:Gem::Requirement
27
+ requirement: &2160138980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2160245720
35
+ version_requirements: *2160138980
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: yard
38
- requirement: &2160245260 !ruby/object:Gem::Requirement
38
+ requirement: &2160138280 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2160245260
46
+ version_requirements: *2160138280
47
47
  description: Allows ruby objects to implement equality comparison and inspection methods.
48
48
  By including this module, a class indicates that its instances have explicit general
49
49
  contracts for `hash`, `==` and `eql?` methods.
@@ -65,6 +65,9 @@ files:
65
65
  - lib/equatable.rb
66
66
  - lib/equatable/version.rb
67
67
  - spec/equatable/eql_spec.rb
68
+ - spec/equatable/equal_spec.rb
69
+ - spec/equatable/include_spec.rb
70
+ - spec/equatable/subclass_spec.rb
68
71
  - spec/spec_helper.rb
69
72
  homepage: http://github.com/peter-murach/equatable
70
73
  licenses: []
@@ -92,5 +95,8 @@ specification_version: 3
92
95
  summary: Allows ruby objects to implement equality comparison and inspection methods.
93
96
  test_files:
94
97
  - spec/equatable/eql_spec.rb
98
+ - spec/equatable/equal_spec.rb
99
+ - spec/equatable/include_spec.rb
100
+ - spec/equatable/subclass_spec.rb
95
101
  - spec/spec_helper.rb
96
102
  has_rdoc: