template_class 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/.rspec +3 -0
- data/.rubocop.yml +451 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +57 -0
- data/LICENSE +21 -0
- data/README.md +102 -0
- data/Rakefile +12 -0
- data/lib/template_class/template.rb +64 -0
- data/lib/template_class/version.rb +5 -0
- data/lib/template_class.rb +9 -0
- data/sig/template_class.rbs +4 -0
- metadata +80 -0
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
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
data/Gemfile
ADDED
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,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
|
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: []
|