template_class 1.0.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
+ SHA256:
3
+ metadata.gz: 600465ef851b0f80d3a893cef379527402986a6ca048535849d7fd9f769821fb
4
+ data.tar.gz: 2d51acb9d3b421458d24bba27e31106f82f9d839d34748597b2860bfb4ab6ad8
5
+ SHA512:
6
+ metadata.gz: 58d7c41b98d98a4d145c4830e05edfc3234be729baf8a6bcae7b3d2a13797c26b4aa36ec2ac71f0d75531e668e0fafde0e0a9bbced5fda9e0e7933fa5ff69f0e
7
+ data.tar.gz: c569ddaf85a09f3bf8c60b667aa06ed313a9e6cf657b05dac11d03782f7a0b56cb231882cb9911532c13438667e2110a76f42e7add1d933bafdd82ce983e2b1f
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,451 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/**'
4
+
5
+ Gemspec/DeprecatedAttributeAssignment:
6
+ Enabled: true
7
+
8
+ Gemspec/DevelopmentDependencies:
9
+ Enabled: true
10
+
11
+ Gemspec/RequireMFA:
12
+ Enabled: false
13
+
14
+ Layout/AccessModifierIndentation:
15
+ EnforcedStyle: outdent
16
+
17
+ Layout/BeginEndAlignment:
18
+ EnforcedStyleAlignWith: begin
19
+
20
+ Layout/BlockAlignment:
21
+ EnforcedStyleAlignWith: start_of_block
22
+
23
+ Layout/CommentIndentation:
24
+ AllowForAlignment: true
25
+
26
+ Layout/EmptyLineAfterMultilineCondition:
27
+ Enabled: true
28
+
29
+ Layout/EndOfLine:
30
+ EnforcedStyle: lf
31
+
32
+ Layout/ExtraSpacing:
33
+ AllowForAlignment: true
34
+ AllowBeforeTrailingComments: true
35
+
36
+ Layout/HashAlignment:
37
+ EnforcedHashRocketStyle: table
38
+ EnforcedColonStyle: table
39
+ EnforcedLastArgumentHashStyle: ignore_implicit
40
+
41
+ Layout/LineContinuationLeadingSpace:
42
+ Enabled: true
43
+
44
+ Layout/LineContinuationSpacing:
45
+ Enabled: true
46
+
47
+ Layout/LineEndStringConcatenationIndentation:
48
+ Enabled: true
49
+
50
+ Layout/MultilineArrayLineBreaks:
51
+ Enabled: true
52
+
53
+ Layout/MultilineAssignmentLayout:
54
+ Enabled: true
55
+ EnforcedStyle: same_line
56
+
57
+ Layout/MultilineHashKeyLineBreaks:
58
+ Enabled: true
59
+
60
+ Layout/MultilineMethodArgumentLineBreaks:
61
+ Enabled: true
62
+
63
+ Layout/MultilineMethodCallIndentation:
64
+ EnforcedStyle: indented_relative_to_receiver
65
+
66
+ Layout/SingleLineBlockChain:
67
+ Enabled: true
68
+
69
+ Layout/SpaceAroundEqualsInParameterDefault:
70
+ EnforcedStyle: no_space
71
+
72
+ Layout/SpaceAroundOperators:
73
+ EnforcedStyleForExponentOperator: space
74
+
75
+ Layout/SpaceBeforeBrackets:
76
+ Enabled: true
77
+
78
+ Layout/SpaceInsideHashLiteralBraces:
79
+ EnforcedStyle: no_space
80
+
81
+ Layout/TrailingWhitespace:
82
+ AllowInHeredoc: true
83
+
84
+ Lint/AmbiguousAssignment:
85
+ Enabled: true
86
+
87
+ Lint/AmbiguousOperatorPrecedence:
88
+ Enabled: true
89
+
90
+ Lint/AmbiguousRange:
91
+ Enabled: true
92
+ RequireParenthesesForMethodChains: true
93
+
94
+ Lint/AssignmentInCondition:
95
+ AllowSafeAssignment: false
96
+
97
+ Lint/ConstantOverwrittenInRescue:
98
+ Enabled: true
99
+
100
+ Lint/DeprecatedConstants:
101
+ Enabled: true
102
+
103
+ Lint/DuplicateBranch:
104
+ Enabled: true
105
+ IgnoreLiteralBranches: true
106
+ IgnoreConstantBranches: true
107
+
108
+ Lint/DuplicateMagicComment:
109
+ Enabled: true
110
+
111
+ Lint/DuplicateRegexpCharacterClassElement:
112
+ Enabled: true
113
+
114
+ Lint/EmptyBlock:
115
+ Enabled: true
116
+
117
+ Lint/EmptyClass:
118
+ Enabled: true
119
+ AllowComments: true
120
+
121
+ Lint/EmptyInPattern:
122
+ Enabled: true
123
+
124
+ Lint/HeredocMethodCallPosition:
125
+ Enabled: true
126
+
127
+ Lint/IncompatibleIoSelectWithFiberScheduler:
128
+ Enabled: false
129
+
130
+ Lint/LambdaWithoutLiteralBlock:
131
+ Enabled: true
132
+
133
+ Lint/NoReturnInBeginEndBlocks:
134
+ Enabled: true
135
+
136
+ Lint/NonAtomicFileOperation:
137
+ Enabled: true
138
+
139
+ Lint/NumberedParameterAssignment:
140
+ Enabled: true
141
+
142
+ Lint/OrAssignmentToConstant:
143
+ Enabled: true
144
+
145
+ Lint/RedundantDirGlobSort:
146
+ Enabled: true
147
+
148
+ Lint/RedundantSplatExpansion:
149
+ AllowPercentLiteralArrayArgument: false
150
+
151
+ Lint/RefinementImportMethods:
152
+ Enabled: true
153
+
154
+ Lint/RequireRangeParentheses:
155
+ Enabled: true
156
+
157
+ Lint/RequireRelativeSelfPath:
158
+ Enabled: true
159
+
160
+ Lint/SymbolConversion:
161
+ Enabled: true
162
+
163
+ Lint/ToEnumArguments:
164
+ Enabled: true
165
+
166
+ Lint/TripleQuotes:
167
+ Enabled: true
168
+
169
+ Lint/UnexpectedBlockArity:
170
+ Enabled: true
171
+
172
+ Lint/UnmodifiedReduceAccumulator:
173
+ Enabled: true
174
+
175
+ Lint/UnusedBlockArgument:
176
+ AutoCorrect: false
177
+
178
+ Lint/UnusedMethodArgument:
179
+ AutoCorrect: false
180
+
181
+ Lint/UselessRescue:
182
+ Enabled: true
183
+
184
+ Lint/UselessRuby2Keywords:
185
+ Enabled: true
186
+
187
+ Metrics:
188
+ Enabled: false
189
+
190
+ Naming/BlockForwarding:
191
+ Enabled: true
192
+
193
+ Naming/InclusiveLanguage:
194
+ Enabled: false
195
+
196
+ Security/CompoundHash:
197
+ Enabled: true
198
+
199
+ Security/Eval:
200
+ Enabled: false
201
+
202
+ Security/IoMethods:
203
+ Enabled: true
204
+
205
+ Style/AccessorGrouping:
206
+ EnforcedStyle: separated
207
+
208
+ Style/ArgumentsForwarding:
209
+ Enabled: false
210
+
211
+ Style/ArrayIntersect:
212
+ Enabled: true
213
+
214
+ Style/AutoResourceCleanup:
215
+ Enabled: true
216
+
217
+ Style/CollectionCompact:
218
+ Enabled: true
219
+
220
+ Style/CollectionMethods:
221
+ Enabled: true
222
+
223
+ Style/ComparableClamp:
224
+ Enabled: true
225
+
226
+ Style/ConcatArrayLiterals:
227
+ Enabled: true
228
+
229
+ Style/DirEmpty:
230
+ Enabled: true
231
+
232
+ Style/DocumentDynamicEvalDefinition:
233
+ Enabled: false
234
+
235
+ Style/Documentation:
236
+ Enabled: false
237
+
238
+ Style/DocumentationMethod:
239
+ Enabled: false
240
+
241
+ Style/DoubleNegation:
242
+ EnforcedStyle: forbidden
243
+
244
+ Style/EmptyHeredoc:
245
+ Enabled: true
246
+
247
+ Style/EmptyMethod:
248
+ EnforcedStyle: expanded
249
+
250
+ Style/EndlessMethod:
251
+ Enabled: true
252
+ EnforcedStyle: disallow
253
+
254
+ Style/EnvHome:
255
+ Enabled: true
256
+
257
+ Style/FetchEnvVar:
258
+ Enabled: false
259
+
260
+ Style/FileEmpty:
261
+ Enabled: true
262
+
263
+ Style/FileRead:
264
+ Enabled: true
265
+
266
+ Style/FileWrite:
267
+ Enabled: true
268
+
269
+ Style/FormatString:
270
+ EnforcedStyle: percent
271
+
272
+ Style/FrozenStringLiteralComment:
273
+ Enabled: false
274
+
275
+ Style/HashConversion:
276
+ Enabled: true
277
+
278
+ Style/HashExcept:
279
+ Enabled: true
280
+
281
+ Style/HashSyntax:
282
+ EnforcedShorthandSyntax: never
283
+
284
+ Style/IfWithBooleanLiteralBranches:
285
+ Enabled: true
286
+
287
+ Style/ImplicitRuntimeError:
288
+ Enabled: true
289
+
290
+ Style/InPatternThen:
291
+ Enabled: true
292
+
293
+ Style/IpAddresses:
294
+ Enabled: true
295
+
296
+ Style/MagicCommentFormat:
297
+ Enabled: true
298
+
299
+ Style/MapCompactWithConditionalBlock:
300
+ Enabled: true
301
+
302
+ Style/MapToHash:
303
+ Enabled: true
304
+
305
+ Style/MapToSet:
306
+ Enabled: true
307
+
308
+ Style/MethodCallWithArgsParentheses:
309
+ Enabled: true
310
+ EnforcedStyle: omit_parentheses
311
+ AllowParenthesesInMultilineCall: true
312
+ AllowParenthesesInChaining: true
313
+ AllowParenthesesInCamelCaseMethod: true
314
+
315
+ Style/MethodDefParentheses:
316
+ EnforcedStyle: require_no_parentheses_except_multiline
317
+
318
+ Style/MinMaxComparison:
319
+ Enabled: true
320
+
321
+ Style/MultilineBlockChain:
322
+ Enabled: false
323
+
324
+ Style/MultilineInPatternThen:
325
+ Enabled: true
326
+
327
+ Style/NegatedIfElseCondition:
328
+ Enabled: true
329
+
330
+ Style/NestedFileDirname:
331
+ Enabled: true
332
+
333
+ Style/NestedParenthesizedCalls:
334
+ Enabled: false
335
+
336
+ Style/NilLambda:
337
+ Enabled: true
338
+
339
+ Style/NonNilCheck:
340
+ Enabled: false
341
+
342
+ Style/NumberedParameters:
343
+ Enabled: true
344
+ EnforcedStyle: disallow
345
+
346
+ Style/NumberedParametersLimit:
347
+ Enabled: true
348
+
349
+ Style/ObjectThen:
350
+ Enabled: true
351
+
352
+ Style/OpenStructUse:
353
+ Enabled: false
354
+
355
+ Style/OperatorMethodCall:
356
+ Enabled: true
357
+
358
+ Style/OptionHash:
359
+ Enabled: true
360
+
361
+ Style/QuotedSymbols:
362
+ Enabled: true
363
+
364
+ Style/RedundantArgument:
365
+ Enabled: false
366
+
367
+ Style/RedundantConstantBase:
368
+ Enabled: false
369
+
370
+ Style/RedundantDoubleSplatHashBraces:
371
+ Enabled: true
372
+
373
+ Style/RedundantEach:
374
+ Enabled: true
375
+
376
+ Style/RedundantException:
377
+ Enabled: false
378
+
379
+ Style/RedundantHeredocDelimiterQuotes:
380
+ Enabled: true
381
+
382
+ Style/RedundantInitialize:
383
+ Enabled: true
384
+
385
+ Style/RedundantParentheses:
386
+ Enabled: false
387
+
388
+ Style/RedundantSelfAssignmentBranch:
389
+ Enabled: true
390
+
391
+ Style/RedundantStringEscape:
392
+ Enabled: true
393
+
394
+ Style/RegexpLiteral:
395
+ EnforcedStyle: percent_r
396
+
397
+ Style/ReturnNil:
398
+ Enabled: true
399
+
400
+ Style/SelectByRegexp:
401
+ Enabled: true
402
+
403
+ Style/SingleLineMethods:
404
+ AllowIfMethodIsEmpty: false
405
+
406
+ Style/StaticClass:
407
+ Enabled: true
408
+
409
+ Style/StringChars:
410
+ Enabled: true
411
+
412
+ Style/StringHashKeys:
413
+ Enabled: false
414
+
415
+ Style/SwapValues:
416
+ Enabled: true
417
+
418
+ Style/SymbolArray:
419
+ EnforcedStyle: brackets
420
+
421
+ Style/TernaryParentheses:
422
+ EnforcedStyle: require_parentheses_when_complex
423
+ AllowSafeAssignment: false
424
+
425
+ Style/TopLevelMethodDefinition:
426
+ Enabled: true
427
+
428
+ Style/TrailingCommaInArguments:
429
+ Enabled: true
430
+ EnforcedStyleForMultiline: no_comma
431
+
432
+ Style/TrailingCommaInArrayLiteral:
433
+ Enabled: true
434
+ EnforcedStyleForMultiline: no_comma
435
+
436
+ Style/TrailingCommaInBlockArgs:
437
+ Enabled: true
438
+
439
+ Style/TrailingCommaInHashLiteral:
440
+ Enabled: true
441
+ EnforcedStyleForMultiline: no_comma
442
+
443
+ Style/UnlessLogicalOperators:
444
+ EnforcedStyle: forbid_logical_operators
445
+
446
+ Style/WordArray:
447
+ EnforcedStyle: brackets
448
+
449
+ Style/YodaCondition:
450
+ Enabled: true
451
+ EnforcedStyle: forbid_for_all_comparison_operators
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ [//]: # (
4
+ ## <Release number> <Date YYYY-MM-DD>
5
+ ### Breaking changes
6
+ ### Deprecations
7
+ ### New features
8
+ ### Bug fixes
9
+ )
10
+
11
+ ## 1.0.0 2023-04-07
12
+
13
+ First release. Refer to [README.md](README.md) for the full documentation.
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in template_class.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+
10
+ gem 'rspec', '~> 3.0'
11
+
12
+ gem 'rubocop', '~> 1.21'
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
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
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Moku S.r.l., Riccardo Agatea
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Template Class
2
+
3
+ A way to define templated classes, in a similar fashion to C++ templates.
4
+
5
+ In most cases Ruby doesn't need templated classes, nor any other system of generics, because it isn't statically type checked. However, sometimes we need to automatically generate multiple similar classes, either because of poor design or because of external necessities. For example, to define a GraphQL schema with [GraphQL Ruby](https://graphql-ruby.org/) we need to define a distinct class for each type. Since GraphQL is statically type checked but doesn't provide generics, if we need a set of similar but distinct types we're left to define them one by one.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'template_class', '~> 1.0'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```bash
18
+ $ bundle
19
+ ```
20
+
21
+ Or you can install the gem on its own:
22
+
23
+ ```bash
24
+ gem install template_class
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Include `TemplateClass::Template` in the class or module you want to make into a template. You can't make instances of a template; instead, you need to *specialize* it to some parameter. By default, any new specialization is an empty class. To define how a specialization is defined from a parameter, call `resolve_template_specialization`. The block you pass will be yielded the parameter that's specializing the template and a class constructor that makes it possible to recursively use the new specialization.
30
+
31
+ ```ruby
32
+ class List
33
+ include TemplateClass::Template
34
+
35
+ resolve_template_specialization do |item_type, klass|
36
+ klass.new do
37
+ define_method :initialize do |items|
38
+ unless items.all? {|item| item.is_a? item_type}
39
+ raise ArgumentError
40
+ end
41
+
42
+ @items = items
43
+ end
44
+
45
+ define_method :push do |item|
46
+ raise ArgumentError unless item.is_a? item_type
47
+
48
+ @items.push item
49
+ end
50
+
51
+ def pop
52
+ @items.pop
53
+ end
54
+ end
55
+ end
56
+ end
57
+ ```
58
+
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
+
61
+ `klass.new` also redefines `inspect` and `to_s` for the new class, so in strings it will appear with the usual C++ style:
62
+
63
+ ```ruby
64
+ List[Integer].to_s # => List<Integer>
65
+ ```
66
+
67
+ If a specific specialization needs to be defined separately, you can set it explicitly. This will behave like a C++ full specialization.
68
+
69
+ ```ruby
70
+ List[:any] = Array
71
+ ```
72
+
73
+ Notice that the parameter isn't constrained to classes: you can use any object.
74
+
75
+ ## Plans for future development
76
+
77
+ - Multiple specialization parameters
78
+ - Partial specialization
79
+
80
+ ## Version numbers
81
+
82
+ Template Class loosely follows [Semantic Versioning](https://semver.org/), with a hard guarantee that breaking changes to the public API will always coincide with an increase to the `MAJOR` number.
83
+
84
+ Version numbers are in three parts: `MAJOR.MINOR.PATCH`.
85
+
86
+ - Breaking changes to the public API increment the `MAJOR`. There may also be changes that would otherwise increase the `MINOR` or the `PATCH`.
87
+ - Additions, deprecations, and "big" non breaking changes to the public API increment the `MINOR`. There may also be changes that would otherwise increase the `PATCH`.
88
+ - Bug fixes and "small" non breaking changes to the public API increment the `PATCH`.
89
+
90
+ Notice that any feature deprecated by a minor release can be expected to be removed by the next major release.
91
+
92
+ ## Changelog
93
+
94
+ Full list of changes in [CHANGELOG.md](CHANGELOG.md)
95
+
96
+ ## Contributing
97
+
98
+ Bug reports and pull requests are welcome on GitHub at https://github.com/moku-io/template_class.
99
+
100
+ ## License
101
+
102
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new :spec
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: [:spec, :rubocop]
@@ -0,0 +1,64 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/core_ext/module/delegation'
3
+ require 'active_support/core_ext/module/attribute_accessors'
4
+
5
+ module TemplateClass
6
+ module Template
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ next unless is_a? Class
11
+
12
+ mattr_reader :cache,
13
+ default: Hash.new { |h, k|
14
+ h[k] = Class.new
15
+ },
16
+ instance_accessor: false
17
+
18
+ singleton_class.delegate :[], :[]=, to: :cache
19
+ singleton_class.undef_method :new
20
+ end
21
+
22
+ class CacheClassConstructor
23
+ attr_reader :key
24
+ attr_reader :owner
25
+
26
+ delegate_missing_to :owner
27
+
28
+ def initialize key, owner
29
+ @key = key
30
+ @owner = owner
31
+ end
32
+
33
+ def new base_class=::Object, &block
34
+ klass = Class.new base_class
35
+ owner[key] = klass
36
+
37
+ outer_self = self
38
+
39
+ klass.define_singleton_method :to_s do
40
+ "#{outer_self.owner}<#{outer_self.key}>"
41
+ end
42
+
43
+ klass.singleton_class.alias_method :inspect, :to_s
44
+
45
+ klass.class_exec(&block)
46
+ klass
47
+ end
48
+ end
49
+ private_constant :CacheClassConstructor
50
+
51
+ class_methods do
52
+ def resolve_template_specialization &block
53
+ cache.default_proc = proc do |h, k|
54
+ class_constructor = CacheClassConstructor.new k, self
55
+ result = block.call k, class_constructor
56
+
57
+ h[k] = result unless h.key? k
58
+
59
+ result
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TemplateClass
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'template_class/version'
4
+
5
+ module TemplateClass
6
+ class Error < StandardError; end
7
+ end
8
+
9
+ require_relative 'template_class/template'
@@ -0,0 +1,4 @@
1
+ module TemplateClass
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: template_class
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Moku S.r.l.
8
+ - Riccardo Agatea
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2023-04-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 7.0.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 7.0.0
28
+ description: In most cases Ruby doesn't need templated classes, nor any other system
29
+ of generics, because it isn't statically type checked. However, sometimes we need
30
+ to automatically generate multiple similar classes, either because of poor design
31
+ or because of external necessities. For example, to define a GraphQL schema with
32
+ GraphQL Ruby (https://graphql-ruby.org/) we need to define a distinct class for
33
+ each type. Since GraphQL is statically type checked but doesn't provide generics,
34
+ if we need a set of similar but distinct types we're left to define them one by
35
+ one.
36
+ email:
37
+ - info@moku.io
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - ".rspec"
43
+ - ".rubocop.yml"
44
+ - CHANGELOG.md
45
+ - Gemfile
46
+ - Gemfile.lock
47
+ - LICENSE
48
+ - README.md
49
+ - Rakefile
50
+ - lib/template_class.rb
51
+ - lib/template_class/template.rb
52
+ - lib/template_class/version.rb
53
+ - sig/template_class.rbs
54
+ homepage: https://github.com/moku-io/template_class
55
+ licenses:
56
+ - MIT
57
+ metadata:
58
+ homepage_uri: https://github.com/moku-io/template_class
59
+ source_code_uri: https://github.com/moku-io/template_class
60
+ changelog_uri: https://github.com/moku-io/template_class
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 3.0.0
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubygems_version: 3.4.6
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: A way to define templated classes, in a similar fashion to C++ templates.
80
+ test_files: []