dry-equalizer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 331c7852ce35d03c2bf636b387de9f0dfda2ff0f
4
+ data.tar.gz: 34c7ecb5014f00f1134b8217b70931f38787d384
5
+ SHA512:
6
+ metadata.gz: bf4777f0013c80f11093c59b9efe78b1b3b7a877f0bf4c0dc7fe2542b435a6756712ece41ea76a3d677ab1c6e97741c10e3680b85ebc1b445a055b704097d8f6
7
+ data.tar.gz: de3f710c92e3c9a849ec37f4c7ef32d015d1634a0794140894647b74068a11dca02de706a2c07dab615902f3f8230bdfa305d70716635e48f7b52bcf9b276d4f
data/.gitignore ADDED
@@ -0,0 +1,39 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## Rubinius
17
+ *.rbc
18
+ .rbx
19
+
20
+ ## PROJECT::GENERAL
21
+ *.gem
22
+ coverage
23
+ profiling
24
+ turbulence
25
+ rdoc
26
+ pkg
27
+ tmp
28
+ doc
29
+ log
30
+ .yardoc
31
+ measurements
32
+
33
+ ## BUNDLER
34
+ .bundle
35
+ Gemfile.lock
36
+ bin
37
+ bundle
38
+
39
+ ## PROJECT::SPECIFIC
data/.rspec ADDED
@@ -0,0 +1,6 @@
1
+ --backtrace
2
+ --color
3
+ --format progress
4
+ --order random
5
+ --profile
6
+ --warnings
data/.rubocop.yml ADDED
File without changes
data/.travis.yml ADDED
@@ -0,0 +1,22 @@
1
+ language: ruby
2
+ bundler_args: --without yard guard benchmarks
3
+ script: "bundle exec rake ci"
4
+ cache: bundler
5
+ sudo: false
6
+ rvm:
7
+ - 2.1
8
+ - 2.2
9
+ - ruby-head
10
+ - rbx-2
11
+ matrix:
12
+ include:
13
+ - rvm: jruby-9000
14
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug --2.0" # for simplecov
15
+ - rvm: jruby-head
16
+ env: JRUBY_OPTS="$JRUBY_OPTS --debug --2.0" # for simplecov
17
+ allow_failures:
18
+ - rvm: jruby-9000
19
+ - rvm: jruby-head
20
+ - rvm: rbx-2
21
+ - rvm: ruby-head
22
+ fast_finish: true
data/.yardstick.yml ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 100
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # v0.1.0 2015-11-11
2
+
3
+ ## Added
4
+
5
+ - `Dry::Equalizer()` method accepting a list of keys (solnic)
6
+
7
+ ## Changed
8
+
9
+ - `eql?` no longer tries to coerce `other` with `coerce` method (solnic)
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,11 @@
1
+ Contributing
2
+ ------------
3
+
4
+ * If you want your code merged into the mainline, please discuss the proposed changes with me before doing any work on it. This library is still in early development, and the direction it is going may not always be clear. Some features may not be appropriate yet, may need to be deferred until later when the foundation for them is laid, or may be more applicable in a plugin.
5
+ * Fork the project.
6
+ * Make your feature addition or bug fix.
7
+ * Follow this [style guide](https://github.com/dkubb/styleguide).
8
+ * Add specs for it. This is important so I don't break it in a future version unintentionally. Tests must cover all branches within the code, and code must be fully covered.
9
+ * Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
10
+ * Run "rake ci". This must pass and not show any regressions in the metrics for the code to be merged.
11
+ * Send me a pull request. Bonus points for topic branches.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ group :development, :test do
6
+ gem 'devtools', git: 'https://github.com/mbj/devtools.git'
7
+ end
8
+
9
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009-2013 Dan Kubb
2
+ Copyright (c) 2012 Markus Schirp (packaging)
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,88 @@
1
+ dry-equalizer
2
+ =========
3
+
4
+ Module to define equality, equivalence and inspection methods
5
+
6
+ [![Gem Version](http://img.shields.io/gem/v/equalizer.svg)][gem]
7
+ [![Build Status](http://img.shields.io/travis/dryrb/dry-equalizer.svg)][travis]
8
+ [![Dependency Status](http://img.shields.io/gemnasium/dryrb/dry-equalizer.svg)][gemnasium]
9
+ [![Code Climate](http://img.shields.io/codeclimate/github/dryrb/dry-equalizer.svg)][codeclimate]
10
+
11
+ [gem]: https://rubygems.org/gems/equalizer
12
+ [travis]: https://travis-ci.org/dryrb/dry-equalizer
13
+ [gemnasium]: https://gemnasium.com/dryrb/dry-equalizer
14
+ [codeclimate]: https://codeclimate.com/github/dryrb/dry-equalizer
15
+
16
+ Examples
17
+ --------
18
+
19
+ ``` ruby
20
+ class GeoLocation
21
+ include Equalizer.new(:latitude, :longitude)
22
+
23
+ attr_reader :latitude, :longitude
24
+
25
+ def initialize(latitude, longitude)
26
+ @latitude, @longitude = latitude, longitude
27
+ end
28
+ end
29
+
30
+ point_a = GeoLocation.new(1, 2)
31
+ point_b = GeoLocation.new(1, 2)
32
+ point_c = GeoLocation.new(2, 2)
33
+
34
+ point_a.inspect # => "#<GeoLocation latitude=1 longitude=2>"
35
+
36
+ point_a == point_b # => true
37
+ point_a.hash == point_b.hash # => true
38
+ point_a.eql?(point_b) # => true
39
+ point_a.equal?(point_b) # => false
40
+
41
+ point_a == point_c # => false
42
+ point_a.hash == point_c.hash # => false
43
+ point_a.eql?(point_c) # => false
44
+ point_a.equal?(point_c) # => false
45
+ ```
46
+
47
+ Supported Ruby Versions
48
+ -----------------------
49
+
50
+ This library aims to support and is [tested against][travis] the following Ruby
51
+ implementations:
52
+
53
+ * Ruby 2.1
54
+ * Ruby 2.2
55
+
56
+ If something doesn't work on one of these versions, it's a bug.
57
+
58
+ This library may inadvertently work (or seem to work) on other Ruby versions or
59
+ implementations, however support will only be provided for the implementations
60
+ listed above.
61
+
62
+ If you would like this library to support another Ruby version or
63
+ implementation, you may volunteer to be a maintainer. Being a maintainer
64
+ entails making sure all tests run and pass on that implementation. When
65
+ something breaks on your implementation, you will be responsible for providing
66
+ patches in a timely fashion. If critical issues for a particular implementation
67
+ exist at the time of a major release, support for that Ruby version may be
68
+ dropped.
69
+
70
+ Credits
71
+ -------
72
+
73
+ This is a fork of the original [equalizer](https://github.com/dkubb/equalizer).
74
+
75
+ * Dan Kubb ([dkubb](https://github.com/dkubb))
76
+ * Piotr Solnica ([solnic](https://github.com/solnic))
77
+ * Markus Schirp ([mbj](https://github.com/mbj))
78
+ * Erik Michaels-Ober ([sferik](https://github.com/sferik))
79
+
80
+ Contributing
81
+ -------------
82
+
83
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
84
+
85
+ Copyright
86
+ ---------
87
+
88
+ Copyright &copy; 2009-2013 Dan Kubb. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler'
2
+ require 'devtools'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+ Devtools.init_rake_tasks
@@ -0,0 +1,2 @@
1
+ ---
2
+ unit_test_timeout: 1.0
data/config/flay.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ threshold: 0
3
+ total_score: 0
4
+ lib_dirs: []
data/config/flog.yml ADDED
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 15.6
3
+ lib_dirs: ['lib']
data/config/mutant.yml ADDED
@@ -0,0 +1,2 @@
1
+ name: equalizer
2
+ namespace: Equalizer
data/config/reek.yml ADDED
@@ -0,0 +1,105 @@
1
+ ---
2
+ Attribute:
3
+ enabled: false
4
+ exclude: []
5
+ BooleanParameter:
6
+ enabled: true
7
+ exclude: []
8
+ ClassVariable:
9
+ enabled: true
10
+ exclude: []
11
+ ControlParameter:
12
+ enabled: true
13
+ exclude: []
14
+ DataClump:
15
+ enabled: true
16
+ exclude: []
17
+ max_copies: 2
18
+ min_clump_size: 2
19
+ DuplicateMethodCall:
20
+ enabled: true
21
+ exclude: []
22
+ max_calls: 1
23
+ allow_calls: []
24
+ FeatureEnvy:
25
+ enabled: true
26
+ exclude: []
27
+ IrresponsibleModule:
28
+ enabled: true
29
+ exclude: []
30
+ LongParameterList:
31
+ enabled: true
32
+ exclude: []
33
+ max_params: 2
34
+ overrides:
35
+ initialize:
36
+ max_params: 3
37
+ LongYieldList:
38
+ enabled: true
39
+ exclude: []
40
+ max_params: 2
41
+ NestedIterators:
42
+ enabled: true
43
+ exclude:
44
+ - Equalizer#define_cmp_method
45
+ - Equalizer#define_inspect_method
46
+ max_allowed_nesting: 1
47
+ ignore_iterators: []
48
+ NilCheck:
49
+ enabled: true
50
+ exclude: []
51
+ RepeatedConditional:
52
+ enabled: true
53
+ exclude: []
54
+ max_ifs: 1
55
+ TooManyInstanceVariables:
56
+ enabled: true
57
+ exclude: []
58
+ max_instance_variables: 3
59
+ TooManyMethods:
60
+ enabled: true
61
+ exclude: []
62
+ max_methods: 6
63
+ TooManyStatements:
64
+ enabled: true
65
+ exclude:
66
+ - Equalizer#define_inspect_method
67
+ max_statements: 5
68
+ UncommunicativeMethodName:
69
+ enabled: true
70
+ exclude: []
71
+ reject:
72
+ - !ruby/regexp /^[a-z]$/
73
+ - !ruby/regexp /[0-9]$/
74
+ - !ruby/regexp /[A-Z]/
75
+ accept: []
76
+ UncommunicativeModuleName:
77
+ enabled: true
78
+ exclude: []
79
+ reject:
80
+ - !ruby/regexp /^.$/
81
+ - !ruby/regexp /[0-9]$/
82
+ accept: []
83
+ UncommunicativeParameterName:
84
+ enabled: true
85
+ exclude: []
86
+ reject:
87
+ - !ruby/regexp /^.$/
88
+ - !ruby/regexp /[0-9]$/
89
+ - !ruby/regexp /[A-Z]/
90
+ accept: []
91
+ UncommunicativeVariableName:
92
+ enabled: true
93
+ exclude: []
94
+ reject:
95
+ - !ruby/regexp /^.$/
96
+ - !ruby/regexp /[0-9]$/
97
+ - !ruby/regexp /[A-Z]/
98
+ accept: []
99
+ UnusedParameters:
100
+ enabled: true
101
+ exclude: []
102
+ UtilityFunction:
103
+ enabled: true
104
+ exclude: []
105
+ max_helper_calls: 0
@@ -0,0 +1,115 @@
1
+ # Avoid parameter lists longer than five parameters.
2
+ ParameterLists:
3
+ Max: 3
4
+ CountKeywordArgs: true
5
+
6
+ # Avoid more than `Max` levels of nesting.
7
+ BlockNesting:
8
+ Max: 3
9
+
10
+ # Align with the style guide.
11
+ CollectionMethods:
12
+ PreferredMethods:
13
+ collect: 'map'
14
+ inject: 'reduce'
15
+ find: 'detect'
16
+ find_all: 'select'
17
+
18
+ # Do not force public/protected/private keyword to be indented at the same
19
+ # level as the def keyword. My personal preference is to outdent these keywords
20
+ # because I think when scanning code it makes it easier to identify the
21
+ # sections of code and visually separate them. When the keyword is at the same
22
+ # level I think it sort of blends in with the def keywords and makes it harder
23
+ # to scan the code and see where the sections are.
24
+ AccessModifierIndentation:
25
+ Enabled: false
26
+
27
+ # Limit line length
28
+ LineLength:
29
+ Max: 106
30
+
31
+ # Disable documentation checking until a class needs to be documented once
32
+ Documentation:
33
+ Enabled: false
34
+
35
+ # Do not always use &&/|| instead of and/or.
36
+ AndOr:
37
+ Enabled: false
38
+
39
+ # Do not favor modifier if/unless usage when you have a single-line body
40
+ IfUnlessModifier:
41
+ Enabled: false
42
+
43
+ # Allow case equality operator (in limited use within the specs)
44
+ CaseEquality:
45
+ Enabled: false
46
+
47
+ # Constants do not always have to use SCREAMING_SNAKE_CASE
48
+ ConstantName:
49
+ Enabled: false
50
+
51
+ # Not all trivial readers/writers can be defined with attr_* methods
52
+ TrivialAccessors:
53
+ Enabled: false
54
+
55
+ # Allow empty lines around class body
56
+ EmptyLinesAroundClassBody:
57
+ Enabled: false
58
+
59
+ # Allow empty lines around module body
60
+ EmptyLinesAroundModuleBody:
61
+ Enabled: false
62
+
63
+ # Allow empty lines around block body
64
+ EmptyLinesAroundBlockBody:
65
+ Enabled: false
66
+
67
+ # Allow multiple line operations to not require indentation
68
+ MultilineOperationIndentation:
69
+ Enabled: false
70
+
71
+ # Prefer String#% over Kernel#sprintf
72
+ FormatString:
73
+ Enabled: false
74
+
75
+ # Use square brackets for literal Array objects
76
+ PercentLiteralDelimiters:
77
+ PreferredDelimiters:
78
+ '%': '{}'
79
+ '%i': '[]'
80
+ '%q': ()
81
+ '%Q': ()
82
+ '%r': '{}'
83
+ '%s': ()
84
+ '%w': '[]'
85
+ '%W': '[]'
86
+ '%x': ()
87
+
88
+ # Use %i[...] for arrays of symbols
89
+ SymbolArray:
90
+ Enabled: true
91
+
92
+ # Align if/else blocks with the variable assignment
93
+ EndAlignment:
94
+ AlignWith: variable
95
+
96
+ # Do not always align parameters when it is easier to read
97
+ AlignParameters:
98
+ Exclude:
99
+ - spec/**/*_spec.rb
100
+
101
+ # Prefer #kind_of? over #is_a?
102
+ ClassCheck:
103
+ EnforcedStyle: kind_of?
104
+
105
+ # Do not prefer double quotes to be used when %q or %Q is more appropriate
106
+ UnneededPercentQ:
107
+ Enabled: false
108
+
109
+ # Allow a maximum ABC score
110
+ Metrics/AbcSize:
111
+ Max: 8.6
112
+
113
+ # Do not prefer lambda.call(...) over lambda.(...)
114
+ LambdaCall:
115
+ Enabled: false
@@ -0,0 +1,34 @@
1
+ ---
2
+ path: 'lib/**/*.rb'
3
+ threshold: 100
4
+ rules:
5
+ ApiTag::Presence:
6
+ enabled: true
7
+ exclude: []
8
+ ApiTag::Inclusion:
9
+ enabled: true
10
+ exclude: []
11
+ ApiTag::ProtectedMethod:
12
+ enabled: true
13
+ exclude: []
14
+ ApiTag::PrivateMethod:
15
+ enabled: true
16
+ exclude: []
17
+ ExampleTag:
18
+ enabled: true
19
+ exclude: []
20
+ ReturnTag:
21
+ enabled: true
22
+ exclude: []
23
+ Summary::Presence:
24
+ enabled: true
25
+ exclude: []
26
+ Summary::Length:
27
+ enabled: true
28
+ exclude: []
29
+ Summary::Delimiter:
30
+ enabled: true
31
+ exclude: []
32
+ Summary::SingleLine:
33
+ enabled: true
34
+ exclude: []
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../lib/dry/equalizer/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'dry-equalizer'
7
+ gem.version = Dry::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 = '>= 2.1.0'
21
+
22
+ gem.add_development_dependency('bundler', '~> 1.3', '>= 1.3.5')
23
+ end
@@ -0,0 +1 @@
1
+ require 'dry/equalizer'
@@ -0,0 +1,129 @@
1
+ # encoding: utf-8
2
+
3
+ module Dry
4
+ # Build an equalizer module for the inclusion in other class
5
+ #
6
+ # @api public
7
+ def self.Equalizer(*keys)
8
+ Dry::Equalizer.new(*keys)
9
+ end
10
+
11
+ # Define equality, equivalence and inspection methods
12
+ class Equalizer < Module
13
+ # Initialize an Equalizer with the given keys
14
+ #
15
+ # Will use the keys with which it is initialized to define #cmp?,
16
+ # #hash, and #inspect
17
+ #
18
+ # @param [Array<Symbol>] keys
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ def initialize(*keys)
24
+ @keys = keys
25
+ define_methods
26
+ freeze
27
+ end
28
+
29
+ private
30
+
31
+ # Hook called when module is included
32
+ #
33
+ # @param [Module] descendant
34
+ # the module or class including Equalizer
35
+ #
36
+ # @return [self]
37
+ #
38
+ # @api private
39
+ def included(descendant)
40
+ super
41
+ descendant.include Methods
42
+ end
43
+
44
+ # Define the equalizer methods based on #keys
45
+ #
46
+ # @return [undefined]
47
+ #
48
+ # @api private
49
+ def define_methods
50
+ define_cmp_method
51
+ define_hash_method
52
+ define_inspect_method
53
+ end
54
+
55
+ # Define an #cmp? method based on the instance's values identified by #keys
56
+ #
57
+ # @return [undefined]
58
+ #
59
+ # @api private
60
+ def define_cmp_method
61
+ keys = @keys
62
+ define_method(:cmp?) do |comparator, other|
63
+ keys.all? do |key|
64
+ __send__(key).public_send(comparator, other.__send__(key))
65
+ end
66
+ end
67
+ private :cmp?
68
+ end
69
+
70
+ # Define a #hash method based on the instance's values identified by #keys
71
+ #
72
+ # @return [undefined]
73
+ #
74
+ # @api private
75
+ def define_hash_method
76
+ keys = @keys
77
+ define_method(:hash) do | |
78
+ keys.map(&method(:send)).push(self.class).hash
79
+ end
80
+ end
81
+
82
+ # Define an inspect method that reports the values of the instance's keys
83
+ #
84
+ # @return [undefined]
85
+ #
86
+ # @api private
87
+ def define_inspect_method
88
+ keys = @keys
89
+ define_method(:inspect) do | |
90
+ klass = self.class
91
+ name = klass.name || klass.inspect
92
+ "#<#{name}#{keys.map { |key| " #{key}=#{__send__(key).inspect}" }.join}>"
93
+ end
94
+ end
95
+
96
+ # The comparison methods
97
+ module Methods
98
+ # Compare the object with other object for equality
99
+ #
100
+ # @example
101
+ # object.eql?(other) # => true or false
102
+ #
103
+ # @param [Object] other
104
+ # the other object to compare with
105
+ #
106
+ # @return [Boolean]
107
+ #
108
+ # @api public
109
+ def eql?(other)
110
+ instance_of?(other.class) && cmp?(__method__, other)
111
+ end
112
+
113
+ # Compare the object with other object for equivalency
114
+ #
115
+ # @example
116
+ # object == other # => true or false
117
+ #
118
+ # @param [Object] other
119
+ # the other object to compare with
120
+ #
121
+ # @return [Boolean]
122
+ #
123
+ # @api public
124
+ def ==(other)
125
+ other.kind_of?(self.class) && cmp?(__method__, other)
126
+ end
127
+ end # module Methods
128
+ end # class Equalizer
129
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ module Dry
4
+ class Equalizer < Module
5
+ # Gem version
6
+ VERSION = '0.1.0'.freeze
7
+ end # class Equalizer
8
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ if ENV['COVERAGE'] == 'true'
4
+ require 'simplecov'
5
+
6
+ SimpleCov.start do
7
+ command_name 'spec:unit'
8
+
9
+ add_filter 'config'
10
+ add_filter 'spec'
11
+ add_filter 'vendor'
12
+
13
+ minimum_coverage 100
14
+ end
15
+ end
16
+
17
+ require 'devtools/spec_helper'
18
+ require 'dry-equalizer'
19
+
20
+ RSpec.configure do |config|
21
+ config.raise_errors_for_deprecations!
22
+
23
+ config.expect_with :rspec do |expect_with|
24
+ expect_with.syntax = :expect
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rbconfig'
4
+
5
+ ::Config = RbConfig unless defined?(::Config)
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Dry::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
+ allow(described_class::Methods).to receive(: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 Dry::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.kind_of?(Dry::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
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Dry::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 Dry::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
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Dry::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 Dry::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 a different object' do
80
+ let(:other) { described_class.new(false) }
81
+
82
+ it { should be(false) }
83
+
84
+ it 'is symmetric' do
85
+ should eql(other == object)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,158 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Dry::Equalizer do
6
+ let(:object) { described_class }
7
+ let(:name) { 'User' }
8
+ let(:klass) { ::Class.new }
9
+
10
+ context 'with no keys' do
11
+ subject { Dry::Equalizer() }
12
+
13
+ before do
14
+ # specify the class #name method
15
+ allow(klass).to receive(: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).map(&: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 { Dry::Equalizer(*keys) }
77
+
78
+ let(:keys) { %i[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 = firstname
90
+ @lastname = lastname
91
+ end
92
+ end
93
+ end
94
+
95
+ before do
96
+ # specify the class #inspect method
97
+ allow(klass).to receive_messages(name: nil, inspect: 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).map(&: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
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dry-equalizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan Kubb
8
+ - Markus Schirp
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-11-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.3.5
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '1.3'
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.3.5
34
+ description: Module to define equality, equivalence and inspection methods
35
+ email:
36
+ - dan.kubb@gmail.com
37
+ - mbj@schirp-dso.com
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files:
41
+ - LICENSE
42
+ - README.md
43
+ - CONTRIBUTING.md
44
+ files:
45
+ - ".gitignore"
46
+ - ".rspec"
47
+ - ".rubocop.yml"
48
+ - ".travis.yml"
49
+ - ".yardstick.yml"
50
+ - CHANGELOG.md
51
+ - CONTRIBUTING.md
52
+ - Gemfile
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - config/devtools.yml
57
+ - config/flay.yml
58
+ - config/flog.yml
59
+ - config/mutant.yml
60
+ - config/reek.yml
61
+ - config/rubocop.yml
62
+ - config/yardstick.yml
63
+ - dry-equalizer.gemspec
64
+ - lib/dry-equalizer.rb
65
+ - lib/dry/equalizer.rb
66
+ - lib/dry/equalizer/version.rb
67
+ - spec/spec_helper.rb
68
+ - spec/support/config_alias.rb
69
+ - spec/unit/equalizer/included_spec.rb
70
+ - spec/unit/equalizer/methods/eql_predicate_spec.rb
71
+ - spec/unit/equalizer/methods/equality_operator_spec.rb
72
+ - spec/unit/equalizer/universal_spec.rb
73
+ homepage: https://github.com/dkubb/equalizer
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 2.1.0
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.4.5
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Module to define equality, equivalence and inspection methods
97
+ test_files:
98
+ - spec/unit/equalizer/included_spec.rb
99
+ - spec/unit/equalizer/methods/eql_predicate_spec.rb
100
+ - spec/unit/equalizer/methods/equality_operator_spec.rb
101
+ - spec/unit/equalizer/universal_spec.rb
102
+ has_rdoc: