key_set 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rspec +3 -0
- data/.rubocop.yml +45 -0
- data/.travis.yml +18 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +202 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/rake +29 -0
- data/bin/setup +8 -0
- data/key_set.gemspec +33 -0
- data/lib/key_set.rb +107 -0
- data/lib/key_set/all.rb +52 -0
- data/lib/key_set/all_except_some.rb +73 -0
- data/lib/key_set/based_on_keys.rb +35 -0
- data/lib/key_set/none.rb +52 -0
- data/lib/key_set/some.rb +72 -0
- data/lib/key_set/version.rb +5 -0
- metadata +122 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 19b39d7fc11b72e1276d84da44d947775f5e9acf845c4aba7315123ac62c9c6f
|
4
|
+
data.tar.gz: b9947bc238a8d186bacb4cbcf1ba1b9884ddc7d43e86d0faee90fbf66308c953
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa0b11f3bb468889a750c344758494a6ac765da00e6861dad29e828300a53d464ee2aea11621319607ec5642d49560e6e1e34759b2ea416dceda25cd95e3d512
|
7
|
+
data.tar.gz: b9b2284b2da74bddd52253d76a44a9701ea4c60a22a4b0ffb77b6b3419ae32c8a3747daa12fce6c13b73f4935530c83d266d3760aa60da2194615163ed027f71
|
data/.gitignore
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile '~/.gitignore_global'
|
6
|
+
|
7
|
+
# Ignore bundler config.
|
8
|
+
/.idea
|
9
|
+
/.bundle
|
10
|
+
|
11
|
+
# Ignore all logfiles and tempfiles.
|
12
|
+
/log/*
|
13
|
+
/tmp/*
|
14
|
+
!/log/.keep
|
15
|
+
!/tmp/.keep
|
16
|
+
|
17
|
+
# Ignore Byebug command history file.
|
18
|
+
.byebug_history
|
19
|
+
/coverage
|
20
|
+
/manual_sandbox.json
|
21
|
+
/brakeman.out.json
|
22
|
+
.DS_Store
|
23
|
+
|
24
|
+
# gem
|
25
|
+
/.yardoc
|
26
|
+
/_yardoc/
|
27
|
+
/coverage/
|
28
|
+
/doc/
|
29
|
+
/pkg/
|
30
|
+
/spec/reports/
|
31
|
+
|
32
|
+
# rspec failure tracking
|
33
|
+
.rspec_status
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
Exclude:
|
6
|
+
- 'bin/**/*'
|
7
|
+
- 'vendor/**/*'
|
8
|
+
- 'spec/fixtures/**/*'
|
9
|
+
- 'tmp/**/*'
|
10
|
+
- 'db/schema.rb'
|
11
|
+
TargetRubyVersion: 2.5
|
12
|
+
|
13
|
+
Rails:
|
14
|
+
Enabled: true
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Max: 140
|
18
|
+
IgnoredPatterns: ['^[\s]*#']
|
19
|
+
|
20
|
+
Metrics/MethodLength:
|
21
|
+
Max: 15
|
22
|
+
|
23
|
+
Style/SymbolArray:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/Documentation:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
RSpec/MultipleExpectations:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
RSpec/ExampleLength:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
RSpec/ContextWording:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
RSpec/HookArgument:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Style/TrailingCommaInArrayLiteral:
|
42
|
+
EnforcedStyleForMultiline: comma
|
43
|
+
|
44
|
+
Style/TrailingCommaInHashLiteral:
|
45
|
+
EnforcedStyleForMultiline: comma
|
data/.travis.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
---
|
2
|
+
env:
|
3
|
+
global:
|
4
|
+
- CC_TEST_REPORTER_ID=1eec0569f37168d92ce0fbdecced22b50ba2e3425c309ed67b8e8685864acf6c
|
5
|
+
language: ruby
|
6
|
+
sudo: false
|
7
|
+
cache: bundler
|
8
|
+
rvm:
|
9
|
+
- 2.5.3
|
10
|
+
before_install: gem install bundler -v 1.17.1
|
11
|
+
before_script:
|
12
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
13
|
+
- chmod +x ./cc-test-reporter
|
14
|
+
- ./cc-test-reporter before-build
|
15
|
+
script:
|
16
|
+
- bundle exec rspec
|
17
|
+
after_script:
|
18
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at eturino@eturino.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
key_set (1.0.0)
|
5
|
+
activesupport (>= 4)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (5.2.1)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (>= 0.7, < 2)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
concurrent-ruby (1.0.5)
|
16
|
+
diff-lcs (1.3)
|
17
|
+
docile (1.3.1)
|
18
|
+
i18n (1.1.1)
|
19
|
+
concurrent-ruby (~> 1.0)
|
20
|
+
json (2.1.0)
|
21
|
+
minitest (5.11.3)
|
22
|
+
rake (10.5.0)
|
23
|
+
rspec (3.8.0)
|
24
|
+
rspec-core (~> 3.8.0)
|
25
|
+
rspec-expectations (~> 3.8.0)
|
26
|
+
rspec-mocks (~> 3.8.0)
|
27
|
+
rspec-core (3.8.0)
|
28
|
+
rspec-support (~> 3.8.0)
|
29
|
+
rspec-expectations (3.8.2)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.8.0)
|
32
|
+
rspec-mocks (3.8.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.8.0)
|
35
|
+
rspec-support (3.8.0)
|
36
|
+
simplecov (0.16.1)
|
37
|
+
docile (~> 1.1)
|
38
|
+
json (>= 1.8, < 3)
|
39
|
+
simplecov-html (~> 0.10.0)
|
40
|
+
simplecov-html (0.10.2)
|
41
|
+
thread_safe (0.3.6)
|
42
|
+
tzinfo (1.2.5)
|
43
|
+
thread_safe (~> 0.1)
|
44
|
+
|
45
|
+
PLATFORMS
|
46
|
+
ruby
|
47
|
+
|
48
|
+
DEPENDENCIES
|
49
|
+
bundler (~> 1.17)
|
50
|
+
key_set!
|
51
|
+
rake (~> 10.0)
|
52
|
+
rspec (~> 3.0)
|
53
|
+
simplecov
|
54
|
+
|
55
|
+
BUNDLED WITH
|
56
|
+
1.17.1
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2018 Eduardo Turiño
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
# KeySet
|
2
|
+
|
3
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/eea7d889d4f13fbf45c7/maintainability)](https://codeclimate.com/github/eturino/ruby_key_set/maintainability)
|
4
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/eea7d889d4f13fbf45c7/test_coverage)](https://codeclimate.com/github/eturino/ruby_key_set/test_coverage)
|
5
|
+
[![Build Status](https://travis-ci.org/eturino/ruby_key_set.svg?branch=master)](https://travis-ci.org/eturino/ruby_key_set)
|
6
|
+
[![Gem Version](https://badge.fury.io/rb/key_set.svg)](https://badge.fury.io/rb/key_set)
|
7
|
+
|
8
|
+
KeySet allows you to represent the 4 possible sets of elements:
|
9
|
+
|
10
|
+
- All elements (`KeySet.all # => KeySet::All`)
|
11
|
+
- No elements (`KeySet.non # => KeySet::None`)
|
12
|
+
- Some elements (`KeySet.some(['k1', 'k2']) # => KeySet::Some`)
|
13
|
+
- All except some elements (`KeySet.all_except_some(['k1', 'k2']) # => KeySet::AllExceptSome`)
|
14
|
+
|
15
|
+
and do some operations on them, like:
|
16
|
+
- calculate inverse KeySet (`key_set.invert`)
|
17
|
+
- remove a KeySet from another KeySet (`key_set.remove(other)`)
|
18
|
+
- intersect 2 KeySets (`key_set.intersect(other)`)
|
19
|
+
|
20
|
+
The keys in the `Some` and `AllExceptSome` key sets are stored in a `SortedSet`, so they are sorted and without duplicates.
|
21
|
+
|
22
|
+
### Creation
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
KeySet.all # => new KeySet of KeySet::All
|
26
|
+
|
27
|
+
KeySet.none # => new KeySet of KeySet::None
|
28
|
+
|
29
|
+
KeySet.some(['k1', 'k2']) # => new KeySet of KeySet::Some with keys ['k1', 'k2']
|
30
|
+
KeySet.some([]) # => same as KeySet.none => returns new KeySet::None
|
31
|
+
|
32
|
+
KeySet.all_except_some(['k1', 'k2']) # => new KeySet of KeySet::AllExceptSome with keys ['k1', 'k2']
|
33
|
+
KeySet.all_except_some([]) # => same as KeySet.all => returns new KeySet::All
|
34
|
+
```
|
35
|
+
|
36
|
+
### Checks
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
key_set.represents_all? # => true if the key set is a KeySet::All
|
40
|
+
key_set.represents_none? # => true if the key set is a KeySet::None
|
41
|
+
```
|
42
|
+
|
43
|
+
### `.invert`
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
KeySet.all.invert # => KeySet::None
|
47
|
+
KeySet.none.invert # => KeySet::None
|
48
|
+
KeySet.some(['k1', 'k2']).invert # => KeySet::AllExceptSome with keys 'k1' and 'k2'
|
49
|
+
KeySet.all_except_some(['k1', 'k2']).invert # => KeySet::Some with keys 'k1' and 'k2'
|
50
|
+
```
|
51
|
+
|
52
|
+
### `.intersect`
|
53
|
+
|
54
|
+
```
|
55
|
+
#intersect
|
56
|
+
All
|
57
|
+
KeySet.all.intersect(KeySet.all)
|
58
|
+
we have everything, we intersect everything => we have everything
|
59
|
+
KeySet.all.intersect(KeySet.none)
|
60
|
+
we have everything, we intersect nothing => we have nothing
|
61
|
+
KeySet.all.intersect(KeySet.some [key1, key2])
|
62
|
+
we have everything, we intersect some => we have some
|
63
|
+
KeySet.all.intersect(KeySet.all_except_some [key1, key2])
|
64
|
+
we have everything, we intersect all except some => we have all except some
|
65
|
+
None
|
66
|
+
KeySet.none.intersect(KeySet.all)
|
67
|
+
we have nothing, we intersect everything => we have nothing
|
68
|
+
KeySet.none.intersect(KeySet.none)
|
69
|
+
we have nothing, we intersect nothing => we have nothing
|
70
|
+
KeySet.none.intersect(KeySet.some [key1, key2])
|
71
|
+
we have nothing, we intersect some => we have nothing
|
72
|
+
KeySet.none.intersect(KeySet.all_except_some [key1, key2])
|
73
|
+
we have nothing, we intersect all except some => we have nothing
|
74
|
+
Some
|
75
|
+
KeySet.some([key1, key3]).intersect(KeySet.all)
|
76
|
+
we have some, we intersect everything => we have the same some
|
77
|
+
KeySet.some([key1, key3]).intersect(KeySet.none)
|
78
|
+
we have some, we intersect nothing => we have nothing
|
79
|
+
KeySet.some([key1, key3]).intersect(KeySet.some [key1, key2])
|
80
|
+
we have some, we intersect some others (that does not include our entire set) => we have the common keys
|
81
|
+
KeySet.some([key1, key3]).intersect(KeySet.some [key1, key2, key3])
|
82
|
+
we have some, we intersect some others that includes our entire set => we have the common keys, so our former set
|
83
|
+
KeySet.some([key1, key3]).intersect(KeySet.all_except_some [key1, key2])
|
84
|
+
we have some, we intersect all except others, which includes some of ours => we have the former keys that are not in the other keys
|
85
|
+
KeySet.some([key1, key3]).intersect(KeySet.all_except_some [key1, key2, key3])
|
86
|
+
we have some, we intersect all except others, which include all our keys => we have nothing
|
87
|
+
KeySet.some([key1, key3]).intersect(KeySet.all_except_some [key2, key4])
|
88
|
+
we have some, we intersect all except others, none of them are in our keys => we have the same set
|
89
|
+
AllExceptSome
|
90
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.all)
|
91
|
+
we have all except some, we intersect everything => we have the same
|
92
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.none)
|
93
|
+
we have all except some, we intersect nothing => we have none
|
94
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.some [key1, key2])
|
95
|
+
we have all except some, we intersect some others => we have the keys in the second that area not in the keys of the first
|
96
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.some [key1, key3])
|
97
|
+
we have all except some, we intersect some of the same keys => we have nothing
|
98
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.some [key1, key2, key3])
|
99
|
+
we have all except some, we intersect some others that includes our entire set => we have the keys in the second that area not in the keys of the first
|
100
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.all_except_some [key1, key2])
|
101
|
+
we have all except some, we intersect all except others (that includes some of the current set) => we get all except the union of keys in the first and in the second
|
102
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.all_except_some [key1, key2, key3])
|
103
|
+
we have all except some, we intersect all except others (that includes the entire of the current set) => we get all except the union of keys in the first and in the second
|
104
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.all_except_some [key2, key4])
|
105
|
+
we have all except some, we intersect all except others (that includes none of the current set) => we get all except the union of keys in the first and in the second
|
106
|
+
KeySet.all_except_some([key1, key3]).intersect(KeySet.all_except_some [key1, key3])
|
107
|
+
we have all except some, we intersect all except others (that has the same set) => we get the same
|
108
|
+
```
|
109
|
+
|
110
|
+
### `.intersect`
|
111
|
+
|
112
|
+
```
|
113
|
+
#remove
|
114
|
+
All
|
115
|
+
KeySet.all.remove(KeySet.all)
|
116
|
+
we have everything, we remove everything => we have nothing
|
117
|
+
KeySet.all.remove(KeySet.none)
|
118
|
+
we have everything, we remove nothing => we have everything
|
119
|
+
KeySet.all.remove(KeySet.some [key1, key2])
|
120
|
+
we have everything, we remove some => we have all except those
|
121
|
+
KeySet.all.remove(KeySet.all_except_some [key1, key2])
|
122
|
+
we have everything, we remove all except some => we have only those
|
123
|
+
None
|
124
|
+
KeySet.none.remove(KeySet.all)
|
125
|
+
we have nothing, we remove everything => we have nothing
|
126
|
+
KeySet.none.remove(KeySet.none)
|
127
|
+
we have nothing, we remove nothing => we have nothing
|
128
|
+
KeySet.none.remove(KeySet.some [key1, key2])
|
129
|
+
we have nothing, we remove some => we have nothing
|
130
|
+
KeySet.none.remove(KeySet.all_except_some [key1, key2])
|
131
|
+
we have nothing, we remove all except some => we have nothing
|
132
|
+
Some
|
133
|
+
KeySet.some([key1, key3]).remove(KeySet.all)
|
134
|
+
we have some, we remove everything => we have nothing
|
135
|
+
KeySet.some([key1, key3]).remove(KeySet.none)
|
136
|
+
we have some, we remove nothing => we have the same set
|
137
|
+
KeySet.some([key1, key3]).remove(KeySet.some [key1, key2])
|
138
|
+
we have some, we remove some others (that does not include our entire set) => we have the keys that we have not been removed
|
139
|
+
KeySet.some([key1, key3]).remove(KeySet.some [key1, key2, key3])
|
140
|
+
we have some, we remove some others that includes our entire set => we have nothing
|
141
|
+
KeySet.some([key1, key3]).remove(KeySet.all_except_some [key1, key2])
|
142
|
+
we have some, we remove all except others => we have only the keys that we had and they were excluded from the removal
|
143
|
+
KeySet.some([key1, key3]).remove(KeySet.all_except_some [key1, key2, key3])
|
144
|
+
we have some, we remove all except others, which include all our keys => we have the same keys
|
145
|
+
KeySet.some([key1, key3]).remove(KeySet.all_except_some [key2, key4])
|
146
|
+
we have some, we remove all except others, none of them are in our keys => we have nothing
|
147
|
+
AllExceptSome
|
148
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.all)
|
149
|
+
we have all except some, we remove everything => we have nothing
|
150
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.none)
|
151
|
+
we have all except some, we remove nothing => we have the same (all but these keys)
|
152
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.some [key1, key2])
|
153
|
+
we have all except some, we remove some others => we have all except the ones that we didn't have before and the ones that we don't have now
|
154
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.some [key1, key2, key3])
|
155
|
+
we have all except some, we remove some others that includes our entire set => we have all except the new set (that includes the old set)
|
156
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.all_except_some [key1, key2])
|
157
|
+
we have all except some, we remove all except others (that includes some of the current set) => we have only the ones that OTHER did not remove, except the ones that THIS was excluding
|
158
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.all_except_some [key1, key2, key3])
|
159
|
+
we have all except some, we remove all except others (that includes the entire of the current set) => we have only the ones that OTHER did not remove, except the ones that THIS was excluding
|
160
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.all_except_some [key2, key4])
|
161
|
+
we have all except some, we remove all except others (that includes none of the current set) => we get only the ones that the other is not excluding
|
162
|
+
KeySet.all_except_some([key1, key3]).remove(KeySet.all_except_some [key1, key3])
|
163
|
+
we have all except some, we remove all except others (that has the same set) => we get nothing
|
164
|
+
```
|
165
|
+
|
166
|
+
Note that removing a AllExceptSome logs a warning, since it is probably not what you want to do.
|
167
|
+
|
168
|
+
## Installation
|
169
|
+
|
170
|
+
Add this line to your application's Gemfile:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
gem 'key_set'
|
174
|
+
```
|
175
|
+
|
176
|
+
And then execute:
|
177
|
+
|
178
|
+
$ bundle
|
179
|
+
|
180
|
+
Or install it yourself as:
|
181
|
+
|
182
|
+
$ gem install key_set
|
183
|
+
|
184
|
+
## Usage
|
185
|
+
|
186
|
+
## Development
|
187
|
+
|
188
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
189
|
+
|
190
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
191
|
+
|
192
|
+
## Contributing
|
193
|
+
|
194
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/eturino/ruby_key_set. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
195
|
+
|
196
|
+
## License
|
197
|
+
|
198
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
199
|
+
|
200
|
+
## Code of Conduct
|
201
|
+
|
202
|
+
Everyone interacting in the KeySet project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/eturino/ruby_key_set/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "key_set"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/setup
ADDED
data/key_set.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'key_set/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'key_set'
|
9
|
+
spec.version = KeySet::VERSION
|
10
|
+
spec.authors = ['Eduardo Turiño']
|
11
|
+
spec.email = ['eturino@eturino.com']
|
12
|
+
|
13
|
+
spec.summary = <<~TXT
|
14
|
+
KeySet with 4 classes to represent concepts of All, None, Some, and AllExceptSome, the last 2 with a sorted uniq list of keys
|
15
|
+
TXT
|
16
|
+
spec.homepage = 'https://github.com/eturino/ruby_key_set'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = 'exe'
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ['lib']
|
27
|
+
|
28
|
+
spec.add_dependency 'activesupport', '>= 4'
|
29
|
+
|
30
|
+
spec.add_development_dependency 'bundler', '~> 1.17'
|
31
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
|
+
end
|
data/lib/key_set.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/all'
|
4
|
+
class KeySet
|
5
|
+
class Error < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.logger
|
9
|
+
@logger ||= default_logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default_logger
|
13
|
+
require 'logger'
|
14
|
+
::Logger.new($stdout)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.all
|
18
|
+
All.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.none
|
22
|
+
None.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.some(keys)
|
26
|
+
return none if keys.blank?
|
27
|
+
|
28
|
+
Some.new keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.all_except_some(keys)
|
32
|
+
return all if keys.blank?
|
33
|
+
|
34
|
+
AllExceptSome.new keys
|
35
|
+
end
|
36
|
+
|
37
|
+
# COMMON
|
38
|
+
|
39
|
+
def represents_all?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def represents_none?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
# :nocov:
|
48
|
+
# @param other [KeySet]
|
49
|
+
# @return [KeySet]
|
50
|
+
def remove(_other)
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param other [KeySet]
|
55
|
+
# @return [KeySet]
|
56
|
+
def intersect(_other)
|
57
|
+
raise NotImplementedError
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [KeySet]
|
61
|
+
def invert
|
62
|
+
raise NotImplementedError
|
63
|
+
end
|
64
|
+
# :nocov:
|
65
|
+
|
66
|
+
# EQUALITY AND COMPARISON
|
67
|
+
def hash
|
68
|
+
if respond_to? :keys
|
69
|
+
[self.class.to_s, keys.map(&:hash)].hash
|
70
|
+
else
|
71
|
+
self.class.to_s.hash
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def <=>(other)
|
76
|
+
if self.class.class_sort_index == other.class.class_sort_index
|
77
|
+
if respond_to? :keys_array
|
78
|
+
keys_array <=> other.keys_array
|
79
|
+
else
|
80
|
+
0
|
81
|
+
end
|
82
|
+
else
|
83
|
+
self.class.class_sort_index <=> other.class.class_sort_index
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def ===(other)
|
88
|
+
self.class == other.class && try(:keys_array) === other.try(:keys_array) # rubocop:disable Style/CaseEquality
|
89
|
+
end
|
90
|
+
|
91
|
+
def ==(other)
|
92
|
+
self.class == other.class && try(:keys_array) == other.try(:keys_array)
|
93
|
+
end
|
94
|
+
|
95
|
+
def eql?(other)
|
96
|
+
self.class == other.class && try(:keys_array) == other.try(:keys_array)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
require 'key_set/based_on_keys'
|
101
|
+
|
102
|
+
require 'key_set/all'
|
103
|
+
require 'key_set/none'
|
104
|
+
require 'key_set/some'
|
105
|
+
require 'key_set/all_except_some'
|
106
|
+
|
107
|
+
require 'key_set/version'
|
data/lib/key_set/all.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class KeySet
|
4
|
+
class All < KeySet
|
5
|
+
def self.class_sort_index
|
6
|
+
3
|
7
|
+
end
|
8
|
+
|
9
|
+
def represents_all?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def invert
|
14
|
+
KeySet.none
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove(other)
|
18
|
+
case other
|
19
|
+
when All
|
20
|
+
# we have everything, we remove everything => we have nothing
|
21
|
+
KeySet.none
|
22
|
+
when None
|
23
|
+
# we have everything, we remove nothing => we have everything
|
24
|
+
KeySet.all
|
25
|
+
when Some
|
26
|
+
# we have everything, we remove some => we have all except those
|
27
|
+
KeySet.all_except_some other.keys
|
28
|
+
when AllExceptSome
|
29
|
+
# we have everything, we remove all except some => we have only those
|
30
|
+
KeySet.logger.warn "KeySet removing AllButSome, probably a mistake. this: ALL, removing keys: #{other.keys.inspect}"
|
31
|
+
KeySet.some other.keys
|
32
|
+
else
|
33
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def intersect(other)
|
38
|
+
case other
|
39
|
+
when All
|
40
|
+
KeySet.all
|
41
|
+
when None
|
42
|
+
KeySet.none
|
43
|
+
when Some
|
44
|
+
KeySet.some other.keys
|
45
|
+
when AllExceptSome
|
46
|
+
KeySet.all_except_some other.keys
|
47
|
+
else
|
48
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class KeySet
|
4
|
+
class AllExceptSome < KeySet
|
5
|
+
include BasedOnKeys
|
6
|
+
|
7
|
+
def self.class_sort_index
|
8
|
+
2
|
9
|
+
end
|
10
|
+
|
11
|
+
def invert
|
12
|
+
KeySet.some(keys_array)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove(other)
|
16
|
+
case other
|
17
|
+
when All
|
18
|
+
# we have all except some, we remove everything => we have nothing
|
19
|
+
KeySet.none
|
20
|
+
when None
|
21
|
+
# we have all except some, we remove nothing => we have the same (all but these keys)
|
22
|
+
KeySet.all_except_some keys.deep_dup
|
23
|
+
when Some
|
24
|
+
# we have all except some, we remove some others => we have all except the ones that we didn't have before and the ones that we don't have now
|
25
|
+
remove_some(other)
|
26
|
+
when AllExceptSome
|
27
|
+
# we have all except some, we remove all except others => we have only the ones that OTHER did not remove, except the ones that THIS was removing
|
28
|
+
KeySet.logger.warn "KeySet removing AllButSome, probably a mistake. this: ALL_BUT_SOME, removing keys: #{other.keys.inspect}"
|
29
|
+
remove_all_except_some(other)
|
30
|
+
else
|
31
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def intersect(other)
|
36
|
+
case other
|
37
|
+
when All
|
38
|
+
KeySet.all_except_some keys.deep_dup
|
39
|
+
when None
|
40
|
+
KeySet.none
|
41
|
+
when Some
|
42
|
+
# we have all except some, we remove some others => we have all except the ones that we didn't have before and the ones that we don't have now
|
43
|
+
intersect_some(other)
|
44
|
+
when AllExceptSome
|
45
|
+
intersect_all_except_some(other)
|
46
|
+
else
|
47
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def remove_some(other)
|
54
|
+
k = keys.deep_dup + other.keys.deep_dup
|
55
|
+
KeySet.all_except_some k
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_all_except_some(other)
|
59
|
+
k = other.keys.deep_dup - keys.deep_dup
|
60
|
+
KeySet.some k
|
61
|
+
end
|
62
|
+
|
63
|
+
def intersect_some(other)
|
64
|
+
k = other.keys.deep_dup - keys.deep_dup
|
65
|
+
KeySet.some k
|
66
|
+
end
|
67
|
+
|
68
|
+
def intersect_all_except_some(other)
|
69
|
+
k = other.keys.deep_dup + keys.deep_dup
|
70
|
+
KeySet.all_except_some k
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class KeySet
|
4
|
+
module BasedOnKeys
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
attr_reader :keys
|
11
|
+
|
12
|
+
def initialize(keys)
|
13
|
+
@keys = SortedSet.new(keys.to_a)
|
14
|
+
end
|
15
|
+
|
16
|
+
delegate :each, to: :keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def keys_array
|
20
|
+
keys.to_a
|
21
|
+
end
|
22
|
+
|
23
|
+
def represents_all?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def represents_none?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def clone
|
32
|
+
self.class.new keys.deep_dup
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/key_set/none.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class KeySet
|
4
|
+
class None < KeySet
|
5
|
+
def self.class_sort_index
|
6
|
+
0
|
7
|
+
end
|
8
|
+
|
9
|
+
def represents_none?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def invert
|
14
|
+
KeySet.all
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove(other)
|
18
|
+
case other
|
19
|
+
when All
|
20
|
+
# we have nothing, we remove everything => we have nothing
|
21
|
+
KeySet.none
|
22
|
+
when None
|
23
|
+
# we have nothing, we remove nothing => we have nothing
|
24
|
+
KeySet.none
|
25
|
+
when Some
|
26
|
+
# we have nothing, we remove some => we have nothing
|
27
|
+
KeySet.none
|
28
|
+
when AllExceptSome
|
29
|
+
# we have nothing, we remove all except some => we have nothing
|
30
|
+
KeySet.logger.warn "KeySet removing AllButSome, probably a mistake. this: NONE, removing keys: #{other.keys.inspect}"
|
31
|
+
KeySet.none
|
32
|
+
else
|
33
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def intersect(other)
|
38
|
+
case other
|
39
|
+
when All
|
40
|
+
KeySet.none
|
41
|
+
when None
|
42
|
+
KeySet.none
|
43
|
+
when Some
|
44
|
+
KeySet.none
|
45
|
+
when AllExceptSome
|
46
|
+
KeySet.none
|
47
|
+
else
|
48
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/key_set/some.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class KeySet
|
4
|
+
class Some < KeySet
|
5
|
+
include BasedOnKeys
|
6
|
+
|
7
|
+
def self.class_sort_index
|
8
|
+
1
|
9
|
+
end
|
10
|
+
|
11
|
+
def invert
|
12
|
+
KeySet.all_except_some(keys_array)
|
13
|
+
end
|
14
|
+
|
15
|
+
def remove(other)
|
16
|
+
case other
|
17
|
+
when All
|
18
|
+
# we have some, we remove everything => we have nothing
|
19
|
+
KeySet.none
|
20
|
+
when None
|
21
|
+
# we have some, we remove nothing => we have the same set
|
22
|
+
KeySet.some keys.deep_dup
|
23
|
+
when Some
|
24
|
+
# we have some, we remove some others => we have some with another set (or maybe none)
|
25
|
+
remove_some(other)
|
26
|
+
when AllExceptSome
|
27
|
+
# we have some, we remove all except others => we remove all except the intersection
|
28
|
+
KeySet.logger.warn "KeySet removing AllButSome, probably a mistake. this: SOME, removing keys: #{other.keys.inspect}"
|
29
|
+
remove_all_except_some(other)
|
30
|
+
else
|
31
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def intersect(other)
|
36
|
+
case other
|
37
|
+
when All
|
38
|
+
KeySet.some keys.deep_dup
|
39
|
+
when None
|
40
|
+
KeySet.none
|
41
|
+
when Some
|
42
|
+
intersect_with_some(other)
|
43
|
+
when AllExceptSome
|
44
|
+
intersect_with_all_except_some(other)
|
45
|
+
else
|
46
|
+
raise ArgumentError, 'it needs a valid KeySet'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def remove_some(other)
|
53
|
+
k = keys.deep_dup - other.keys.deep_dup
|
54
|
+
KeySet.some k
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove_all_except_some(other)
|
58
|
+
k = keys.deep_dup & other.keys.deep_dup
|
59
|
+
KeySet.some k
|
60
|
+
end
|
61
|
+
|
62
|
+
def intersect_with_all_except_some(other)
|
63
|
+
k = keys.deep_dup - other.keys.deep_dup
|
64
|
+
KeySet.some k
|
65
|
+
end
|
66
|
+
|
67
|
+
def intersect_with_some(other)
|
68
|
+
k = keys.deep_dup & other.keys.deep_dup
|
69
|
+
KeySet.some k
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
metadata
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: key_set
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eduardo Turiño
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- eturino@eturino.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- ".travis.yml"
|
80
|
+
- CODE_OF_CONDUCT.md
|
81
|
+
- Gemfile
|
82
|
+
- Gemfile.lock
|
83
|
+
- LICENSE.txt
|
84
|
+
- README.md
|
85
|
+
- Rakefile
|
86
|
+
- bin/console
|
87
|
+
- bin/rake
|
88
|
+
- bin/setup
|
89
|
+
- key_set.gemspec
|
90
|
+
- lib/key_set.rb
|
91
|
+
- lib/key_set/all.rb
|
92
|
+
- lib/key_set/all_except_some.rb
|
93
|
+
- lib/key_set/based_on_keys.rb
|
94
|
+
- lib/key_set/none.rb
|
95
|
+
- lib/key_set/some.rb
|
96
|
+
- lib/key_set/version.rb
|
97
|
+
homepage: https://github.com/eturino/ruby_key_set
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.7.6
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: KeySet with 4 classes to represent concepts of All, None, Some, and AllExceptSome,
|
121
|
+
the last 2 with a sorted uniq list of keys
|
122
|
+
test_files: []
|