template_class 1.0.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 600465ef851b0f80d3a893cef379527402986a6ca048535849d7fd9f769821fb
4
- data.tar.gz: 2d51acb9d3b421458d24bba27e31106f82f9d839d34748597b2860bfb4ab6ad8
3
+ metadata.gz: e4c0985a84c4d73b07449fea319cd108c0a78477fa0975a0a946dcb82d05dbda
4
+ data.tar.gz: 35cc326a7341985c9d3a416fcad8b58a9465f4e72a083d7c4e9d153ed4f312d4
5
5
  SHA512:
6
- metadata.gz: 58d7c41b98d98a4d145c4830e05edfc3234be729baf8a6bcae7b3d2a13797c26b4aa36ec2ac71f0d75531e668e0fafde0e0a9bbced5fda9e0e7933fa5ff69f0e
7
- data.tar.gz: c569ddaf85a09f3bf8c60b667aa06ed313a9e6cf657b05dac11d03782f7a0b56cb231882cb9911532c13438667e2110a76f42e7add1d933bafdd82ce983e2b1f
6
+ metadata.gz: 1cc67fea8a072fd2fcf64a7bb7b17d22ae801b1547dd92cccd27a0e6f4c939870b032112bf845dc0974d8860d797f4e12c104f19437be369de70e8d0009ff21a
7
+ data.tar.gz: f756b227610d4503557b949dde1ed5f908fac9da1f3353a7dd55a7772f84e145eb419a1fad568f0a497d08d772a29a340b20fc839910ceee92baeedda9cc8065
data/CHANGELOG.md CHANGED
@@ -1,12 +1,29 @@
1
1
  # Changelog
2
2
 
3
- [//]: # (
3
+ <!--[//]: # (
4
4
  ## <Release number> <Date YYYY-MM-DD>
5
5
  ### Breaking changes
6
6
  ### Deprecations
7
7
  ### New features
8
8
  ### Bug fixes
9
- )
9
+ )-->
10
+
11
+ ## 1.2.0 2024-08-19
12
+
13
+ ### New features
14
+
15
+ - Bulk instantiation
16
+
17
+ ## 1.1.0 2023-08-31
18
+
19
+ ### New features
20
+
21
+ - Added support for caching modules.
22
+ - Added RBS type signatures.
23
+
24
+ ### Bug fixes
25
+
26
+ - Removed the `Error` class.
10
27
 
11
28
  ## 1.0.0 2023-04-07
12
29
 
data/README.md CHANGED
@@ -58,7 +58,17 @@ end
58
58
 
59
59
  `klass.new` behaves like `Class.new`, with the key difference that it saves the new class in the internal cache *before* it executes the block in the class scope. If you use `Class.new` the specialization still works as expected, but the class is cached *after* the block is executed, so a loop will be created if the code inside the block references the same specialization it is defining.
60
60
 
61
- `klass.new` also redefines `inspect` and `to_s` for the new class, so in strings it will appear with the usual C++ style:
61
+ A module analogue to `klass` is passed as third parameter to the block:
62
+
63
+ ```ruby
64
+ resolve_template_specialization do |item_type, _, mod|
65
+ mod.new do
66
+ ...
67
+ end
68
+ end
69
+ ```
70
+
71
+ `klass.new` and `mod.new` also redefine `inspect` and `to_s` for the new class/module, so in strings it will appear with the usual C++ style:
62
72
 
63
73
  ```ruby
64
74
  List[Integer].to_s # => List<Integer>
@@ -72,6 +82,32 @@ List[:any] = Array
72
82
 
73
83
  Notice that the parameter isn't constrained to classes: you can use any object.
74
84
 
85
+ ### Bulk Instantiation
86
+
87
+ A module (or class) containing multiple templates can include `TemplateClass::BulkInstanceable` to be able to instantiate them in bulk using the same parameter.
88
+
89
+ ```ruby
90
+ module Templates
91
+ include TemplateClass::BulkInstantiable
92
+
93
+ class Template1
94
+ ...
95
+ end
96
+
97
+ class Template2
98
+ ...
99
+ end
100
+ end
101
+
102
+ module Instances
103
+ Templates.bulk_instance Integer, into: self
104
+ end
105
+ ```
106
+
107
+ The new constants `Instances::Template1` and `Instances::Template2` are now defined, and they point respectively to `Templates::Template1[Integer]` and `Templates::Template2[Integer]`.
108
+
109
+ The optional keyword argument `with_overrides`, which defaults to `true` if `Zeitwerk` is defined and to `false` otherwise, allows you to automatically access and reopen the instances in files that follow the Zeitwerk naming conventions (eg. you can reopen `Instances::Template1` in the file `instances/template1.rb`). If `with_overrides` is `false`, you can still reopen the instances, but you need to manually handle the appropriate `requires` in the appropriate order.
110
+
75
111
  ## Plans for future development
76
112
 
77
113
  - Multiple specialization parameters
@@ -0,0 +1,21 @@
1
+ module TemplateClass
2
+ module BulkInstantiable
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def bulk_instantiate(*args, into:, with_overrides: defined?(Zeitwerk))
7
+ constants(false)
8
+ .map { |constant_name| const_get(constant_name) }
9
+ .map do |constant|
10
+ into.const_set constant.name.demodulize.to_sym, constant[*args]
11
+ end
12
+ .tap { return unless with_overrides } # rubocop:disable Lint/NonLocalExitFromIterator
13
+ .each do |instance|
14
+ require instance.name.underscore
15
+ rescue LoadError
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -46,13 +46,43 @@ module TemplateClass
46
46
  klass
47
47
  end
48
48
  end
49
- private_constant :CacheClassConstructor
49
+
50
+ class CacheModuleConstructor
51
+ attr_reader :key
52
+ attr_reader :owner
53
+
54
+ delegate_missing_to :owner
55
+
56
+ def initialize key, owner
57
+ @key = key
58
+ @owner = owner
59
+ end
60
+
61
+ def new &block
62
+ mod = Module.new
63
+ owner[key] = mod
64
+
65
+ outer_self = self
66
+
67
+ mod.define_singleton_method :to_s do
68
+ "#{outer_self.owner}<#{outer_self.key}>"
69
+ end
70
+
71
+ mod.singleton_class.alias_method :inspect, :to_s
72
+
73
+ mod.module_exec(&block)
74
+ mod
75
+ end
76
+ end
77
+
78
+ private_constant :CacheClassConstructor, :CacheModuleConstructor
50
79
 
51
80
  class_methods do
52
81
  def resolve_template_specialization &block
53
82
  cache.default_proc = proc do |h, k|
54
83
  class_constructor = CacheClassConstructor.new k, self
55
- result = block.call k, class_constructor
84
+ module_constructor = CacheModuleConstructor.new k, self
85
+ result = block.call k, class_constructor, module_constructor
56
86
 
57
87
  h[k] = result unless h.key? k
58
88
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TemplateClass
4
- VERSION = '1.0.0'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -1,9 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require_relative 'template_class/version'
4
-
5
- module TemplateClass
6
- class Error < StandardError; end
7
- end
8
-
9
2
  require_relative 'template_class/template'
3
+ require_relative 'template_class/bulk_instantiable'
@@ -0,0 +1,13 @@
1
+ module TemplateClass
2
+ module Template[T]
3
+ interface _CacheClassConstructor
4
+ def new: (?Class base_class) { () [self: Class] -> void } -> Class
5
+ end
6
+
7
+ interface _CacheModuleConstructor
8
+ def new: () { () [self: Module] -> void } -> Module
9
+ end
10
+
11
+ def resolve_template_specialization: () { (T key, _CacheClassConstructor klass, _CacheModuleConstructor mod) -> Class } -> void
12
+ end
13
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: template_class
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moku S.r.l.
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-04-07 00:00:00.000000000 Z
12
+ date: 2024-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -43,14 +43,14 @@ files:
43
43
  - ".rubocop.yml"
44
44
  - CHANGELOG.md
45
45
  - Gemfile
46
- - Gemfile.lock
47
46
  - LICENSE
48
47
  - README.md
49
48
  - Rakefile
50
49
  - lib/template_class.rb
50
+ - lib/template_class/bulk_instantiable.rb
51
51
  - lib/template_class/template.rb
52
52
  - lib/template_class/version.rb
53
- - sig/template_class.rbs
53
+ - sig/lib/template_class/template.rbs
54
54
  homepage: https://github.com/moku-io/template_class
55
55
  licenses:
56
56
  - MIT
@@ -73,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  requirements: []
76
- rubygems_version: 3.4.6
76
+ rubygems_version: 3.5.11
77
77
  signing_key:
78
78
  specification_version: 4
79
79
  summary: A way to define templated classes, in a similar fashion to C++ templates.
data/Gemfile.lock DELETED
@@ -1,57 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- template_class (1.0.0)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- ast (2.4.2)
10
- diff-lcs (1.5.0)
11
- json (2.6.3)
12
- parallel (1.22.1)
13
- parser (3.2.1.1)
14
- ast (~> 2.4.1)
15
- rainbow (3.1.1)
16
- rake (13.0.6)
17
- regexp_parser (2.7.0)
18
- rexml (3.2.5)
19
- rspec (3.12.0)
20
- rspec-core (~> 3.12.0)
21
- rspec-expectations (~> 3.12.0)
22
- rspec-mocks (~> 3.12.0)
23
- rspec-core (3.12.1)
24
- rspec-support (~> 3.12.0)
25
- rspec-expectations (3.12.2)
26
- diff-lcs (>= 1.2.0, < 2.0)
27
- rspec-support (~> 3.12.0)
28
- rspec-mocks (3.12.4)
29
- diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.12.0)
31
- rspec-support (3.12.0)
32
- rubocop (1.48.1)
33
- json (~> 2.3)
34
- parallel (~> 1.10)
35
- parser (>= 3.2.0.0)
36
- rainbow (>= 2.2.2, < 4.0)
37
- regexp_parser (>= 1.8, < 3.0)
38
- rexml (>= 3.2.5, < 4.0)
39
- rubocop-ast (>= 1.26.0, < 2.0)
40
- ruby-progressbar (~> 1.7)
41
- unicode-display_width (>= 2.4.0, < 3.0)
42
- rubocop-ast (1.27.0)
43
- parser (>= 3.2.1.0)
44
- ruby-progressbar (1.13.0)
45
- unicode-display_width (2.4.2)
46
-
47
- PLATFORMS
48
- arm64-darwin-22
49
-
50
- DEPENDENCIES
51
- rake (~> 13.0)
52
- rspec (~> 3.0)
53
- rubocop (~> 1.21)
54
- template_class!
55
-
56
- BUNDLED WITH
57
- 2.4.6
@@ -1,4 +0,0 @@
1
- module TemplateClass
2
- VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- end