toolcase 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be3b662dfb690e6efe28a29f6f71be36875a97b46db08b64dcd3e8567aa97191
4
- data.tar.gz: ff85f0cf1911494e70209b1f65a34dd20e4efbf0dd79293fe8a1a33fd266dc39
3
+ metadata.gz: 42ab4cde5229fee97fb5723d029c109caa0f20932fa4b9e6dbc17e7a1aec22ed
4
+ data.tar.gz: 5bb7a33c4b6c9ec54c5d456d705f78a4ec1b642bba831428daa78b32357733a5
5
5
  SHA512:
6
- metadata.gz: 8980d73de1ff37211cd66de46b8f3fc78f4edcad93cdae6bdbbb625b5452344c0c53990423abac7684608aadef6a18b8c664b6e1d79261d6b2b8ac9ad68dece0
7
- data.tar.gz: 5f9e7d32cf5dd1c35872dfbe7e10b59355bcb00e85097ed8ed44115ab5176dbcfd94662c783d97cdf19bef5f99f6d823d60f2ff8adf0e9e97e48ed59dfcdd6ff
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.3
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
- TODO: Write usage instructions here
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Toolcase
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/toolcase.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "toolcase/version"
4
+ require_relative "toolcase/registry"
4
5
 
6
+ # Main module
5
7
  module Toolcase
6
- class Error < StandardError; end
7
- # Your code goes here...
8
8
  end
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.3.0")
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.1.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-24 00:00:00.000000000 Z
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.3.0
131
+ version: 2.5.0
131
132
  required_rubygems_version: !ruby/object:Gem::Requirement
132
133
  requirements:
133
134
  - - ">="