toolcase 0.1.0 → 0.2.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 +4 -4
- data/.rubocop.yml +5 -12
- data/README.md +84 -1
- data/lib/toolcase/registry.rb +106 -0
- data/lib/toolcase/version.rb +1 -1
- data/lib/toolcase.rb +2 -2
- data/toolcase.gemspec +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42ab4cde5229fee97fb5723d029c109caa0f20932fa4b9e6dbc17e7a1aec22ed
|
4
|
+
data.tar.gz: 5bb7a33c4b6c9ec54c5d456d705f78a4ec1b642bba831428daa78b32357733a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 229e6fc407eae590b1403245be100df24839c66614e3dfcbaccb9fc43365eb35286e0e494d7f453e25e5ffec0bc29146474caf01a1c60cd1c67a2956d513cb27
|
7
|
+
data.tar.gz: 4668874433002a46ed9b173b1d3e8735500d0c64513b8ed42d1c3a19147fc3b8fcdddeb3a62b9d00f296244d2cc81c513b366c6cc79680cac770d38a28a36655
|
data/.rubocop.yml
CHANGED
@@ -1,16 +1,5 @@
|
|
1
|
-
Style/StringLiterals:
|
2
|
-
Enabled: true
|
3
|
-
EnforcedStyle: double_quotes
|
4
|
-
|
5
|
-
Style/StringLiteralsInInterpolation:
|
6
|
-
Enabled: true
|
7
|
-
EnforcedStyle: double_quotes
|
8
|
-
|
9
|
-
Layout/LineLength:
|
10
|
-
Max: 120
|
11
|
-
|
12
1
|
AllCops:
|
13
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.5
|
14
3
|
NewCops: enable
|
15
4
|
|
16
5
|
Style/StringLiterals:
|
@@ -29,3 +18,7 @@ Style/SingleLineMethods:
|
|
29
18
|
|
30
19
|
Metrics/AbcSize:
|
31
20
|
Max: 20
|
21
|
+
|
22
|
+
Metrics/MethodLength:
|
23
|
+
Exclude:
|
24
|
+
- 'test/registry_modifications_test.rb'
|
data/README.md
CHANGED
@@ -19,7 +19,90 @@ And then execute:
|
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
-
|
22
|
+
Extend a class to convert it into a strategy factory:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class Factory
|
26
|
+
extend Toolcase::Registry
|
27
|
+
|
28
|
+
register Linux
|
29
|
+
register Windows
|
30
|
+
register MacOS
|
31
|
+
register { |it| it.do_something }
|
32
|
+
|
33
|
+
default InvalidOS
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
The `register` method adds an object to the registry. It can be a block or proc.
|
38
|
+
|
39
|
+
A default object can be assigned using the `default` method.
|
40
|
+
The default object, if present, will be returned by default in any search that no object is found.
|
41
|
+
This applies for the `find_by` and `[]` methods.
|
42
|
+
|
43
|
+
`register` methods has the following options:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
class Factory
|
47
|
+
extend Toolcase::Registry
|
48
|
+
|
49
|
+
register Linux, tag: :OS # Registries can be classified with a tag.
|
50
|
+
register OtherStuff, id: :otherstuff # An item can have an identifier.
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
An object can be located in different ways:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
# By id.
|
58
|
+
Factory[:otherstuff]
|
59
|
+
|
60
|
+
# Using the find_by function, which will search through all registries.
|
61
|
+
Factory.find_by { |object| object.handle?(*args) }
|
62
|
+
|
63
|
+
# Search only through items with a specific tag.
|
64
|
+
Factory.find_by(:OS) { |object| object.handle?(*args) }
|
65
|
+
|
66
|
+
# Look up if an specific object belongs to the registry.
|
67
|
+
Factory.include?(object)
|
68
|
+
|
69
|
+
# Look up if an specific object is present in a specific tag.
|
70
|
+
Factory.include?(object, :OS)
|
71
|
+
|
72
|
+
# Get all registries.
|
73
|
+
Factory.registries
|
74
|
+
|
75
|
+
# Get all tagged registries.
|
76
|
+
Factory.registries(:OS)
|
77
|
+
```
|
78
|
+
|
79
|
+
If another class inherits from the Factory, its registries are inherited too.
|
80
|
+
An useful use case is a validator registry, with common validators in base classes,
|
81
|
+
and specific validators in concrete classes.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
class BaseRegistry
|
85
|
+
extend Toolcase::Registry
|
86
|
+
|
87
|
+
register BaseValidator
|
88
|
+
register NonEmpty
|
89
|
+
end
|
90
|
+
|
91
|
+
class SpecificRegistry < BaseRegistry
|
92
|
+
register SpecificValidator
|
93
|
+
end
|
94
|
+
|
95
|
+
SpecificRegistry.size # Returns 3.
|
96
|
+
```
|
97
|
+
|
98
|
+
An item can be replaced or removed using the item id or the item directly.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
Factory.replace(:linux, Ubuntu)
|
102
|
+
Factory.replace(Linux, Ubuntu)
|
103
|
+
Factory.remove(:windows)
|
104
|
+
Factory.remove(Windows)
|
105
|
+
```
|
23
106
|
|
24
107
|
## Development
|
25
108
|
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Toolcase
|
4
|
+
# Registry mixin. Allows to convert a class into a registrable container.
|
5
|
+
# It can then be used to register strategies/handlers and use the class as an abstract factory.
|
6
|
+
module Registry
|
7
|
+
def register(object = nil, id: nil, tag: :nil, &block)
|
8
|
+
element = nil
|
9
|
+
element = object unless object.nil?
|
10
|
+
element = block if block_given?
|
11
|
+
|
12
|
+
return if element.nil? || include?(element)
|
13
|
+
|
14
|
+
elements << element
|
15
|
+
tagged_elements[tag] << element
|
16
|
+
identifiers[id] = element unless id.nil?
|
17
|
+
|
18
|
+
element
|
19
|
+
end
|
20
|
+
|
21
|
+
def default(object = nil)
|
22
|
+
@default = object unless object.nil?
|
23
|
+
defined?(@default) ? @default : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](id)
|
27
|
+
identifiers.fetch(id, default)
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_by(tag = nil, &block)
|
31
|
+
container(tag).find(-> { default }, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def include?(object, tag = nil)
|
35
|
+
container(tag).include?(object)
|
36
|
+
end
|
37
|
+
|
38
|
+
def size(tag = nil)
|
39
|
+
container(tag).size
|
40
|
+
end
|
41
|
+
|
42
|
+
def replace(old_object_or_id, new_object)
|
43
|
+
resolve_object_or_id(old_object_or_id) do |id, element|
|
44
|
+
identifiers[id] = new_object unless id.nil?
|
45
|
+
elements[elements.index(element)] = new_object
|
46
|
+
|
47
|
+
tagged_list = find_in_tagged(element)
|
48
|
+
tagged_list[tagged_list.index(element)] = new_object unless tagged_list.nil?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def remove(object_or_id)
|
53
|
+
resolve_object_or_id(object_or_id) do |id, element|
|
54
|
+
identifiers.delete(id)
|
55
|
+
elements.delete(element)
|
56
|
+
find_in_tagged(element)&.delete(element)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def inherited(child)
|
61
|
+
super
|
62
|
+
child.elements.concat(registries)
|
63
|
+
child.tagged_elements.merge!(tagged_elements)
|
64
|
+
child.identifiers.merge!(identifiers)
|
65
|
+
child.default(default)
|
66
|
+
end
|
67
|
+
|
68
|
+
def registries(tag = nil)
|
69
|
+
container(tag).clone.freeze
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
EMPTY = [].freeze
|
75
|
+
|
76
|
+
def elements
|
77
|
+
@elements ||= []
|
78
|
+
end
|
79
|
+
|
80
|
+
def resolve_object_or_id(obj_or_id)
|
81
|
+
id = identifiers.key?(obj_or_id) ? obj_or_id : identifiers.find { |_, value| value == obj_or_id }&.first
|
82
|
+
element = id.nil? ? obj_or_id : identifiers[id]
|
83
|
+
return unless include?(element)
|
84
|
+
|
85
|
+
yield(id, element)
|
86
|
+
end
|
87
|
+
|
88
|
+
def tagged_elements
|
89
|
+
@tagged_elements ||= Hash.new { |hash, key| hash[key] = [] }
|
90
|
+
end
|
91
|
+
|
92
|
+
def find_in_tagged(element)
|
93
|
+
tagged_elements.find { |_, list| list.include?(element) }&.last
|
94
|
+
end
|
95
|
+
|
96
|
+
def identifiers
|
97
|
+
@identifiers ||= {}
|
98
|
+
end
|
99
|
+
|
100
|
+
def container(tag)
|
101
|
+
return elements if tag.nil?
|
102
|
+
|
103
|
+
tagged_elements.key?(tag) ? tagged_elements[tag] : EMPTY
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/toolcase/version.rb
CHANGED
data/lib/toolcase.rb
CHANGED
data/toolcase.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.summary = "Registry for handlers as a Strategy pattern implementation"
|
11
11
|
spec.homepage = "https://github.com/enchf/toolcase"
|
12
12
|
spec.license = "MIT"
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 2.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
14
14
|
|
15
15
|
spec.metadata["homepage_uri"] = spec.homepage
|
16
16
|
spec.metadata["source_code_uri"] = spec.homepage
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toolcase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- enchf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- bin/console
|
111
111
|
- bin/setup
|
112
112
|
- lib/toolcase.rb
|
113
|
+
- lib/toolcase/registry.rb
|
113
114
|
- lib/toolcase/version.rb
|
114
115
|
- toolcase.gemspec
|
115
116
|
homepage: https://github.com/enchf/toolcase
|
@@ -127,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
128
|
requirements:
|
128
129
|
- - ">="
|
129
130
|
- !ruby/object:Gem::Version
|
130
|
-
version: 2.
|
131
|
+
version: 2.5.0
|
131
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
133
|
requirements:
|
133
134
|
- - ">="
|