equalizer 0.0.10 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -7
- data/.mutant.yml +24 -0
- data/.rubocop.yml +28 -0
- data/.yardopts +4 -0
- data/.yardstick.yml +32 -0
- data/CHANGELOG.md +148 -0
- data/LICENSE +18 -18
- data/README.md +300 -58
- data/Rakefile +47 -27
- data/Steepfile +10 -0
- data/lib/equalizer.rb +152 -89
- data/sig/equalizer.rbs +64 -0
- metadata +46 -71
- data/.gitignore +0 -39
- data/.rspec +0 -6
- data/.ruby-gemset +0 -1
- data/.travis.yml +0 -31
- data/Gemfile +0 -19
- data/config/rubocop.yml +0 -54
- data/equalizer.gemspec +0 -23
- data/lib/equalizer/version.rb +0 -6
- data/spec/spec_helper.rb +0 -26
- data/spec/support/config_alias.rb +0 -5
- data/spec/unit/equalizer/included_spec.rb +0 -50
- data/spec/unit/equalizer/methods/eql_predicate_spec.rb +0 -65
- data/spec/unit/equalizer/methods/equality_operator_spec.rb +0 -108
- data/spec/unit/equalizer/universal_spec.rb +0 -158
data/config/rubocop.yml
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
Metrics/BlockNesting:
|
|
2
|
-
Max: 2
|
|
3
|
-
|
|
4
|
-
Metrics/LineLength:
|
|
5
|
-
AllowURI: true
|
|
6
|
-
Enabled: false
|
|
7
|
-
|
|
8
|
-
Metrics/MethodLength:
|
|
9
|
-
CountComments: false
|
|
10
|
-
Max: 15
|
|
11
|
-
|
|
12
|
-
Metrics/ParameterLists:
|
|
13
|
-
Max: 4
|
|
14
|
-
CountKeywordArgs: true
|
|
15
|
-
|
|
16
|
-
Style/AccessModifierIndentation:
|
|
17
|
-
EnforcedStyle: outdent
|
|
18
|
-
|
|
19
|
-
Style/CollectionMethods:
|
|
20
|
-
PreferredMethods:
|
|
21
|
-
map: 'collect'
|
|
22
|
-
reduce: 'inject'
|
|
23
|
-
find: 'detect'
|
|
24
|
-
find_all: 'select'
|
|
25
|
-
|
|
26
|
-
Style/Documentation:
|
|
27
|
-
Enabled: false
|
|
28
|
-
|
|
29
|
-
Style/DotPosition:
|
|
30
|
-
EnforcedStyle: trailing
|
|
31
|
-
|
|
32
|
-
Style/DoubleNegation:
|
|
33
|
-
Enabled: false
|
|
34
|
-
|
|
35
|
-
Style/EachWithObject:
|
|
36
|
-
Enabled: false
|
|
37
|
-
|
|
38
|
-
Style/Encoding:
|
|
39
|
-
Enabled: false
|
|
40
|
-
|
|
41
|
-
Style/HashSyntax:
|
|
42
|
-
EnforcedStyle: hash_rockets
|
|
43
|
-
|
|
44
|
-
Style/Lambda:
|
|
45
|
-
Enabled: false
|
|
46
|
-
|
|
47
|
-
Style/RaiseArgs:
|
|
48
|
-
EnforcedStyle: compact
|
|
49
|
-
|
|
50
|
-
Style/SpaceInsideHashLiteralBraces:
|
|
51
|
-
EnforcedStyle: no_space
|
|
52
|
-
|
|
53
|
-
Style/TrailingComma:
|
|
54
|
-
EnforcedStyleForMultiline: 'comma'
|
data/equalizer.gemspec
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require File.expand_path('../lib/equalizer/version', __FILE__)
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |gem|
|
|
6
|
-
gem.name = 'equalizer'
|
|
7
|
-
gem.version = Equalizer::VERSION.dup
|
|
8
|
-
gem.authors = ['Dan Kubb', 'Markus Schirp']
|
|
9
|
-
gem.email = %w(dan.kubb@gmail.com mbj@schirp-dso.com)
|
|
10
|
-
gem.description = 'Module to define equality, equivalence and inspection methods'
|
|
11
|
-
gem.summary = gem.description
|
|
12
|
-
gem.homepage = 'https://github.com/dkubb/equalizer'
|
|
13
|
-
gem.licenses = 'MIT'
|
|
14
|
-
|
|
15
|
-
gem.require_paths = %w(lib)
|
|
16
|
-
gem.files = `git ls-files`.split("\n")
|
|
17
|
-
gem.test_files = `git ls-files -- spec/{unit,integration}`.split("\n")
|
|
18
|
-
gem.extra_rdoc_files = %w(LICENSE README.md CONTRIBUTING.md)
|
|
19
|
-
|
|
20
|
-
gem.required_ruby_version = '>= 1.8.7'
|
|
21
|
-
|
|
22
|
-
gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
|
|
23
|
-
end
|
data/lib/equalizer/version.rb
DELETED
data/spec/spec_helper.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
if ENV['COVERAGE'] == 'true'
|
|
4
|
-
require 'simplecov'
|
|
5
|
-
require 'coveralls'
|
|
6
|
-
|
|
7
|
-
SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
|
|
8
|
-
|
|
9
|
-
SimpleCov.start do
|
|
10
|
-
command_name 'spec:unit'
|
|
11
|
-
|
|
12
|
-
add_filter 'config'
|
|
13
|
-
add_filter 'spec'
|
|
14
|
-
add_filter 'vendor'
|
|
15
|
-
|
|
16
|
-
minimum_coverage 100
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
require 'equalizer'
|
|
21
|
-
|
|
22
|
-
RSpec.configure do |config|
|
|
23
|
-
config.expect_with :rspec do |expect_with|
|
|
24
|
-
expect_with.syntax = :expect
|
|
25
|
-
end
|
|
26
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Equalizer, '#included' do
|
|
6
|
-
subject { descendant.instance_exec(object) { |mod| include mod } }
|
|
7
|
-
|
|
8
|
-
let(:object) { described_class.new }
|
|
9
|
-
let(:descendant) { Class.new }
|
|
10
|
-
let(:superclass) { described_class.superclass }
|
|
11
|
-
|
|
12
|
-
before do
|
|
13
|
-
# Prevent Module.included from being called through inheritance
|
|
14
|
-
described_class::Methods.stub(:included)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
around do |example|
|
|
18
|
-
# Restore included method after each example
|
|
19
|
-
superclass.class_eval do
|
|
20
|
-
alias_method :original_included, :included
|
|
21
|
-
example.call
|
|
22
|
-
undef_method :included
|
|
23
|
-
alias_method :included, :original_included
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it 'delegates to the superclass #included method' do
|
|
28
|
-
# This is the most succinct approach I could think of to test whether the
|
|
29
|
-
# superclass#included method is called. All of the built-in rspec helpers
|
|
30
|
-
# did not seem to work for this.
|
|
31
|
-
included = false
|
|
32
|
-
|
|
33
|
-
superclass.class_eval do
|
|
34
|
-
define_method(:included) do |_|
|
|
35
|
-
# Only set the flag when an Equalizer instance is included.
|
|
36
|
-
# Otherwise, other module includes (which get triggered internally
|
|
37
|
-
# in RSpec when `change` is used for the first time, since it uses
|
|
38
|
-
# autoloading for its matchers) will wrongly set this flag.
|
|
39
|
-
included = true if self.is_a?(Equalizer)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
expect { subject }.to change { included }.from(false).to(true)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'includes methods into the descendant' do
|
|
47
|
-
subject
|
|
48
|
-
expect(descendant.included_modules).to include(described_class::Methods)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Equalizer::Methods, '#eql?' do
|
|
6
|
-
subject { object.eql?(other) }
|
|
7
|
-
|
|
8
|
-
let(:object) { described_class.new(true) }
|
|
9
|
-
|
|
10
|
-
let(:described_class) do
|
|
11
|
-
Class.new do
|
|
12
|
-
include Equalizer::Methods
|
|
13
|
-
|
|
14
|
-
attr_reader :boolean
|
|
15
|
-
|
|
16
|
-
def initialize(boolean)
|
|
17
|
-
@boolean = boolean
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def cmp?(comparator, other)
|
|
21
|
-
boolean.send(comparator, other.boolean)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context 'with the same object' do
|
|
27
|
-
let(:other) { object }
|
|
28
|
-
|
|
29
|
-
it { should be(true) }
|
|
30
|
-
|
|
31
|
-
it 'is symmetric' do
|
|
32
|
-
should eql(other.eql?(object))
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context 'with an equivalent object' do
|
|
37
|
-
let(:other) { object.dup }
|
|
38
|
-
|
|
39
|
-
it { should be(true) }
|
|
40
|
-
|
|
41
|
-
it 'is symmetric' do
|
|
42
|
-
should eql(other.eql?(object))
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
context 'with an equivalent object of a subclass' do
|
|
47
|
-
let(:other) { Class.new(described_class).new(true) }
|
|
48
|
-
|
|
49
|
-
it { should be(false) }
|
|
50
|
-
|
|
51
|
-
it 'is symmetric' do
|
|
52
|
-
should eql(other.eql?(object))
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
context 'with a different object' do
|
|
57
|
-
let(:other) { described_class.new(false) }
|
|
58
|
-
|
|
59
|
-
it { should be(false) }
|
|
60
|
-
|
|
61
|
-
it 'is symmetric' do
|
|
62
|
-
should eql(other.eql?(object))
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Equalizer::Methods, '#==' do
|
|
6
|
-
subject { object == other }
|
|
7
|
-
|
|
8
|
-
let(:object) { described_class.new(true) }
|
|
9
|
-
let(:described_class) { Class.new(super_class) }
|
|
10
|
-
|
|
11
|
-
let(:super_class) do
|
|
12
|
-
Class.new do
|
|
13
|
-
include Equalizer::Methods
|
|
14
|
-
|
|
15
|
-
attr_reader :boolean
|
|
16
|
-
|
|
17
|
-
def initialize(boolean)
|
|
18
|
-
@boolean = boolean
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def cmp?(comparator, other)
|
|
22
|
-
boolean.send(comparator, other.boolean)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
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 a subclass instance having equivalent obervable state' do
|
|
48
|
-
let(:other) { Class.new(described_class).new(true) }
|
|
49
|
-
|
|
50
|
-
it { should be(true) }
|
|
51
|
-
|
|
52
|
-
it 'is not symmetric' do
|
|
53
|
-
# the subclass instance should maintain substitutability with the object
|
|
54
|
-
# (in the LSP sense) the reverse is not true.
|
|
55
|
-
should_not eql(other == object)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context 'with a superclass instance having equivalent observable state' do
|
|
60
|
-
let(:other) { super_class.new(true) }
|
|
61
|
-
|
|
62
|
-
it { should be(false) }
|
|
63
|
-
|
|
64
|
-
it 'is not symmetric' do
|
|
65
|
-
should_not eql(other == object)
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
context 'with an object of another class' do
|
|
70
|
-
let(:other) { Class.new.new }
|
|
71
|
-
|
|
72
|
-
it { should be(false) }
|
|
73
|
-
|
|
74
|
-
it 'is symmetric' do
|
|
75
|
-
should eql(other == object)
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
context 'with an equivalent object after coercion' do
|
|
80
|
-
let(:other) { Object.new }
|
|
81
|
-
|
|
82
|
-
before do
|
|
83
|
-
# declare a private #coerce method
|
|
84
|
-
described_class.class_eval do
|
|
85
|
-
def coerce(other)
|
|
86
|
-
[self.class.new(!!other), self]
|
|
87
|
-
end
|
|
88
|
-
private :coerce
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
it { should be(true) }
|
|
93
|
-
|
|
94
|
-
it 'is not symmetric' do
|
|
95
|
-
should_not eql(other == object)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
context 'with a different object' do
|
|
100
|
-
let(:other) { described_class.new(false) }
|
|
101
|
-
|
|
102
|
-
it { should be(false) }
|
|
103
|
-
|
|
104
|
-
it 'is symmetric' do
|
|
105
|
-
should eql(other == object)
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
describe Equalizer, '.new' do
|
|
6
|
-
let(:object) { described_class }
|
|
7
|
-
let(:name) { 'User' }
|
|
8
|
-
let(:klass) { ::Class.new }
|
|
9
|
-
|
|
10
|
-
context 'with no keys' do
|
|
11
|
-
subject { object.new }
|
|
12
|
-
|
|
13
|
-
before do
|
|
14
|
-
# specify the class #name method
|
|
15
|
-
klass.stub(:name).and_return(name)
|
|
16
|
-
klass.send(:include, subject)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
let(:instance) { klass.new }
|
|
20
|
-
|
|
21
|
-
it { should be_instance_of(object) }
|
|
22
|
-
|
|
23
|
-
it { should be_frozen }
|
|
24
|
-
|
|
25
|
-
it 'defines #hash and #inspect methods dynamically' do
|
|
26
|
-
expect(subject.public_instance_methods(false).collect(&:to_s).sort).
|
|
27
|
-
to eql(%w(hash inspect))
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
describe '#eql?' do
|
|
31
|
-
context 'when the objects are similar' do
|
|
32
|
-
let(:other) { instance.dup }
|
|
33
|
-
|
|
34
|
-
it { expect(instance.eql?(other)).to be(true) }
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
context 'when the objects are different' do
|
|
38
|
-
let(:other) { double('other') }
|
|
39
|
-
|
|
40
|
-
it { expect(instance.eql?(other)).to be(false) }
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
describe '#==' do
|
|
45
|
-
context 'when the objects are similar' do
|
|
46
|
-
let(:other) { instance.dup }
|
|
47
|
-
|
|
48
|
-
it { expect(instance == other).to be(true) }
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
context 'when the objects are different' do
|
|
52
|
-
let(:other) { double('other') }
|
|
53
|
-
|
|
54
|
-
it { expect(instance == other).to be(false) }
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe '#hash' do
|
|
59
|
-
it 'has the expected arity' do
|
|
60
|
-
expect(klass.instance_method(:hash).arity).to be(0)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it { expect(instance.hash).to eql([klass].hash) }
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
describe '#inspect' do
|
|
67
|
-
it 'has the expected arity' do
|
|
68
|
-
expect(klass.instance_method(:inspect).arity).to be(0)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it { expect(instance.inspect).to eql('#<User>') }
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
context 'with keys' do
|
|
76
|
-
subject { object.new(*keys) }
|
|
77
|
-
|
|
78
|
-
let(:keys) { [:firstname, :lastname].freeze }
|
|
79
|
-
let(:firstname) { 'John' }
|
|
80
|
-
let(:lastname) { 'Doe' }
|
|
81
|
-
let(:instance) { klass.new(firstname, lastname) }
|
|
82
|
-
|
|
83
|
-
let(:klass) do
|
|
84
|
-
::Class.new do
|
|
85
|
-
attr_reader :firstname, :lastname
|
|
86
|
-
private :firstname, :lastname
|
|
87
|
-
|
|
88
|
-
def initialize(firstname, lastname)
|
|
89
|
-
@firstname, @lastname = firstname, lastname
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
before do
|
|
95
|
-
# specify the class #inspect method
|
|
96
|
-
klass.stub(:name).and_return(nil)
|
|
97
|
-
klass.stub(:inspect).and_return(name)
|
|
98
|
-
klass.send(:include, subject)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it { should be_instance_of(object) }
|
|
102
|
-
|
|
103
|
-
it { should be_frozen }
|
|
104
|
-
|
|
105
|
-
it 'defines #hash and #inspect methods dynamically' do
|
|
106
|
-
expect(subject.public_instance_methods(false).collect(&:to_s).sort).
|
|
107
|
-
to eql(%w(hash inspect))
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
describe '#eql?' do
|
|
111
|
-
context 'when the objects are similar' do
|
|
112
|
-
let(:other) { instance.dup }
|
|
113
|
-
|
|
114
|
-
it { expect(instance.eql?(other)).to be(true) }
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
context 'when the objects are different' do
|
|
118
|
-
let(:other) { double('other') }
|
|
119
|
-
|
|
120
|
-
it { expect(instance.eql?(other)).to be(false) }
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
describe '#==' do
|
|
125
|
-
context 'when the objects are similar' do
|
|
126
|
-
let(:other) { instance.dup }
|
|
127
|
-
|
|
128
|
-
it { expect(instance == other).to be(true) }
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
context 'when the objects are different type' do
|
|
132
|
-
let(:other) { klass.new('Foo', 'Bar') }
|
|
133
|
-
|
|
134
|
-
it { expect(instance == other).to be(false) }
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
context 'when the objects are from different type' do
|
|
138
|
-
let(:other) { double('other') }
|
|
139
|
-
|
|
140
|
-
it { expect(instance == other).to be(false) }
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
describe '#hash' do
|
|
145
|
-
it 'returns the expected hash' do
|
|
146
|
-
expect(instance.hash).
|
|
147
|
-
to eql([firstname, lastname, klass].hash)
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
describe '#inspect' do
|
|
152
|
-
it 'returns the expected string' do
|
|
153
|
-
expect(instance.inspect).
|
|
154
|
-
to eql('#<User firstname="John" lastname="Doe">')
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|