tapioca 0.10.4 → 0.11.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/lib/tapioca/cli.rb +14 -5
- data/lib/tapioca/commands/annotations.rb +2 -0
- data/lib/tapioca/commands/configure.rb +1 -0
- data/lib/tapioca/commands/dsl.rb +17 -3
- data/lib/tapioca/commands/gem.rb +4 -2
- data/lib/tapioca/dsl/compilers/aasm.rb +78 -17
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +3 -3
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +8 -5
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +140 -83
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +74 -0
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +14 -11
- data/lib/tapioca/dsl/compilers/active_resource.rb +22 -15
- data/lib/tapioca/dsl/compilers/active_storage.rb +4 -2
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +21 -1
- data/lib/tapioca/dsl/compilers/kredis.rb +130 -0
- data/lib/tapioca/dsl/compilers/smart_properties.rb +7 -4
- data/lib/tapioca/dsl/compilers/url_helpers.rb +7 -4
- data/lib/tapioca/dsl/extensions/active_record.rb +9 -0
- data/lib/tapioca/dsl/extensions/kredis.rb +114 -0
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +37 -27
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +1 -0
- data/lib/tapioca/dsl/pipeline.rb +12 -5
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +1 -1
- data/lib/tapioca/gem/listeners/yard_doc.rb +13 -10
- data/lib/tapioca/gem/pipeline.rb +14 -0
- data/lib/tapioca/gemfile.rb +6 -2
- data/lib/tapioca/helpers/rbi_files_helper.rb +12 -6
- data/lib/tapioca/helpers/sorbet_helper.rb +7 -4
- data/lib/tapioca/helpers/source_uri.rb +10 -7
- data/lib/tapioca/loaders/gem.rb +4 -2
- data/lib/tapioca/loaders/loader.rb +99 -35
- data/lib/tapioca/rbi_ext/model.rb +8 -3
- data/lib/tapioca/rbi_formatter.rb +11 -8
- data/lib/tapioca/runtime/attached_class_of_32.rb +20 -0
- data/lib/tapioca/runtime/attached_class_of_legacy.rb +27 -0
- data/lib/tapioca/runtime/reflection.rb +11 -10
- data/lib/tapioca/runtime/trackers.rb +17 -0
- data/lib/tapioca/static/symbol_loader.rb +14 -14
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +8 -5
- metadata +7 -2
@@ -164,16 +164,10 @@ module Tapioca
|
|
164
164
|
|
165
165
|
sig { override.void }
|
166
166
|
def decorate
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
create_classes_and_includes(model)
|
173
|
-
create_common_methods(common_relation_methods_module)
|
174
|
-
create_relation_methods(relation_methods_module, association_relation_methods_module)
|
175
|
-
create_association_relation_methods(association_relation_methods_module)
|
176
|
-
end
|
167
|
+
create_classes_and_includes
|
168
|
+
create_common_methods
|
169
|
+
create_relation_methods
|
170
|
+
create_association_relation_methods
|
177
171
|
end
|
178
172
|
|
179
173
|
class << self
|
@@ -181,7 +175,7 @@ module Tapioca
|
|
181
175
|
|
182
176
|
sig { override.returns(T::Enumerable[Module]) }
|
183
177
|
def gather_constants
|
184
|
-
ActiveRecord::Base.
|
178
|
+
descendants_of(ActiveRecord::Base).reject(&:abstract_class?)
|
185
179
|
end
|
186
180
|
end
|
187
181
|
|
@@ -196,28 +190,35 @@ module Tapioca
|
|
196
190
|
T::Array[Symbol],
|
197
191
|
)
|
198
192
|
|
199
|
-
QUERY_METHODS = T.let(
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
193
|
+
QUERY_METHODS = T.let(
|
194
|
+
begin
|
195
|
+
# Grab all Query methods
|
196
|
+
query_methods = ActiveRecord::QueryMethods.instance_methods(false)
|
197
|
+
# Grab all Spawn methods
|
198
|
+
query_methods |= ActiveRecord::SpawnMethods.instance_methods(false)
|
199
|
+
# Remove the ones we know are private API
|
200
|
+
query_methods -= [:arel, :build_subquery, :construct_join_dependency, :extensions, :spawn]
|
201
|
+
# Remove "where" which needs a custom return type for WhereChains
|
202
|
+
query_methods -= [:where]
|
203
|
+
# Remove the methods that ...
|
204
|
+
query_methods
|
205
|
+
.grep_v(/_clause$/) # end with "_clause"
|
206
|
+
.grep_v(/_values?$/) # end with "_value" or "_values"
|
207
|
+
.grep_v(/=$/) # end with "=""
|
208
|
+
.grep_v(/(?<!uniq)!$/) # end with "!" except for "uniq!"
|
209
|
+
end,
|
210
|
+
T::Array[Symbol],
|
211
|
+
)
|
215
212
|
WHERE_CHAIN_QUERY_METHODS = T.let(
|
216
213
|
ActiveRecord::QueryMethods::WhereChain.instance_methods(false),
|
217
214
|
T::Array[Symbol],
|
218
215
|
)
|
219
216
|
FINDER_METHODS = T.let(ActiveRecord::FinderMethods.instance_methods(false), T::Array[Symbol])
|
220
|
-
SIGNED_FINDER_METHODS = T.let(
|
217
|
+
SIGNED_FINDER_METHODS = T.let(
|
218
|
+
defined?(ActiveRecord::SignedId) ? ActiveRecord::SignedId::ClassMethods.instance_methods(false) : [],
|
219
|
+
T::Array[Symbol],
|
220
|
+
)
|
221
|
+
BATCHES_METHODS = T.let(ActiveRecord::Batches.instance_methods(false), T::Array[Symbol])
|
221
222
|
CALCULATION_METHODS = T.let(ActiveRecord::Calculations.instance_methods(false), T::Array[Symbol])
|
222
223
|
ENUMERABLE_QUERY_METHODS = T.let([:any?, :many?, :none?, :one?], T::Array[Symbol])
|
223
224
|
FIND_OR_CREATE_METHODS = T.let(
|
@@ -228,6 +229,38 @@ module Tapioca
|
|
228
229
|
|
229
230
|
private
|
230
231
|
|
232
|
+
sig { returns(RBI::Scope) }
|
233
|
+
def model
|
234
|
+
@model ||= T.let(
|
235
|
+
root.create_path(constant),
|
236
|
+
T.nilable(RBI::Scope),
|
237
|
+
)
|
238
|
+
end
|
239
|
+
|
240
|
+
sig { returns(RBI::Scope) }
|
241
|
+
def relation_methods_module
|
242
|
+
@relation_methods_module ||= T.let(
|
243
|
+
model.create_module(RelationMethodsModuleName),
|
244
|
+
T.nilable(RBI::Scope),
|
245
|
+
)
|
246
|
+
end
|
247
|
+
|
248
|
+
sig { returns(RBI::Scope) }
|
249
|
+
def association_relation_methods_module
|
250
|
+
@association_relation_methods_module ||= T.let(
|
251
|
+
model.create_module(AssociationRelationMethodsModuleName),
|
252
|
+
T.nilable(RBI::Scope),
|
253
|
+
)
|
254
|
+
end
|
255
|
+
|
256
|
+
sig { returns(RBI::Scope) }
|
257
|
+
def common_relation_methods_module
|
258
|
+
@common_relation_methods_module ||= T.let(
|
259
|
+
model.create_module(CommonRelationMethodsModuleName),
|
260
|
+
T.nilable(RBI::Scope),
|
261
|
+
)
|
262
|
+
end
|
263
|
+
|
231
264
|
sig { returns(String) }
|
232
265
|
def constant_name
|
233
266
|
@constant_name ||= T.let(T.must(qualified_name_of(constant)), T.nilable(String))
|
@@ -238,8 +271,8 @@ module Tapioca
|
|
238
271
|
method_name.to_s.end_with?("!")
|
239
272
|
end
|
240
273
|
|
241
|
-
sig {
|
242
|
-
def create_classes_and_includes
|
274
|
+
sig { void }
|
275
|
+
def create_classes_and_includes
|
243
276
|
model.create_extend(CommonRelationMethodsModuleName)
|
244
277
|
# The model always extends the generated relation module
|
245
278
|
model.create_extend(RelationMethodsModuleName)
|
@@ -248,13 +281,13 @@ module Tapioca
|
|
248
281
|
# See https://github.com/sorbet/sorbet/pull/4706 for details
|
249
282
|
model.create_method("to_ary", return_type: "NilClass", visibility: RBI::Private.new)
|
250
283
|
|
251
|
-
create_relation_class
|
252
|
-
create_association_relation_class
|
253
|
-
create_collection_proxy_class
|
284
|
+
create_relation_class
|
285
|
+
create_association_relation_class
|
286
|
+
create_collection_proxy_class
|
254
287
|
end
|
255
288
|
|
256
|
-
sig {
|
257
|
-
def create_relation_class
|
289
|
+
sig { void }
|
290
|
+
def create_relation_class
|
258
291
|
superclass = "::ActiveRecord::Relation"
|
259
292
|
|
260
293
|
# The relation subclass includes the generated relation module
|
@@ -266,11 +299,11 @@ module Tapioca
|
|
266
299
|
klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
|
267
300
|
end
|
268
301
|
|
269
|
-
create_relation_where_chain_class
|
302
|
+
create_relation_where_chain_class
|
270
303
|
end
|
271
304
|
|
272
|
-
sig {
|
273
|
-
def create_association_relation_class
|
305
|
+
sig { void }
|
306
|
+
def create_association_relation_class
|
274
307
|
superclass = "::ActiveRecord::AssociationRelation"
|
275
308
|
|
276
309
|
# Association subclasses include the generated association relation module
|
@@ -282,19 +315,19 @@ module Tapioca
|
|
282
315
|
klass.create_method("to_ary", return_type: "T::Array[#{constant_name}]")
|
283
316
|
end
|
284
317
|
|
285
|
-
create_association_relation_where_chain_class
|
318
|
+
create_association_relation_where_chain_class
|
286
319
|
end
|
287
320
|
|
288
|
-
sig {
|
289
|
-
def create_relation_where_chain_class
|
321
|
+
sig { void }
|
322
|
+
def create_relation_where_chain_class
|
290
323
|
model.create_class(RelationWhereChainClassName, superclass_name: RelationClassName) do |klass|
|
291
324
|
create_where_chain_methods(klass, RelationClassName)
|
292
325
|
klass.create_type_variable("Elem", type: "type_member", fixed: constant_name)
|
293
326
|
end
|
294
327
|
end
|
295
328
|
|
296
|
-
sig {
|
297
|
-
def create_association_relation_where_chain_class
|
329
|
+
sig { void }
|
330
|
+
def create_association_relation_where_chain_class
|
298
331
|
model.create_class(
|
299
332
|
AssociationRelationWhereChainClassName,
|
300
333
|
superclass_name: AssociationRelationClassName,
|
@@ -329,8 +362,8 @@ module Tapioca
|
|
329
362
|
end
|
330
363
|
end
|
331
364
|
|
332
|
-
sig {
|
333
|
-
def create_collection_proxy_class
|
365
|
+
sig { void }
|
366
|
+
def create_collection_proxy_class
|
334
367
|
superclass = "::ActiveRecord::Associations::CollectionProxy"
|
335
368
|
|
336
369
|
# The relation subclass includes the generated association relation module
|
@@ -423,13 +456,11 @@ module Tapioca
|
|
423
456
|
end
|
424
457
|
end
|
425
458
|
|
426
|
-
sig {
|
427
|
-
def create_relation_methods
|
428
|
-
create_relation_method("all"
|
459
|
+
sig { void }
|
460
|
+
def create_relation_methods
|
461
|
+
create_relation_method("all")
|
429
462
|
create_relation_method(
|
430
463
|
"where",
|
431
|
-
relation_methods_module,
|
432
|
-
association_relation_methods_module,
|
433
464
|
parameters: [
|
434
465
|
create_rest_param("args", type: "T.untyped"),
|
435
466
|
create_block_param("blk", type: "T.untyped"),
|
@@ -441,8 +472,6 @@ module Tapioca
|
|
441
472
|
QUERY_METHODS.each do |method_name|
|
442
473
|
create_relation_method(
|
443
474
|
method_name,
|
444
|
-
relation_methods_module,
|
445
|
-
association_relation_methods_module,
|
446
475
|
parameters: [
|
447
476
|
create_rest_param("args", type: "T.untyped"),
|
448
477
|
create_block_param("blk", type: "T.untyped"),
|
@@ -451,8 +480,8 @@ module Tapioca
|
|
451
480
|
end
|
452
481
|
end
|
453
482
|
|
454
|
-
sig {
|
455
|
-
def create_association_relation_methods
|
483
|
+
sig { void }
|
484
|
+
def create_association_relation_methods
|
456
485
|
returning_type = "T.nilable(T.any(T::Array[Symbol], FalseClass))"
|
457
486
|
unique_by_type = "T.nilable(T.any(T::Array[Symbol], Symbol))"
|
458
487
|
|
@@ -496,11 +525,10 @@ module Tapioca
|
|
496
525
|
end
|
497
526
|
end
|
498
527
|
|
499
|
-
sig {
|
500
|
-
def create_common_methods
|
528
|
+
sig { void }
|
529
|
+
def create_common_methods
|
501
530
|
create_common_method(
|
502
531
|
"destroy_all",
|
503
|
-
common_relation_methods_module,
|
504
532
|
return_type: "T::Array[#{constant_name}]",
|
505
533
|
)
|
506
534
|
|
@@ -509,7 +537,6 @@ module Tapioca
|
|
509
537
|
when :exists?
|
510
538
|
create_common_method(
|
511
539
|
"exists?",
|
512
|
-
common_relation_methods_module,
|
513
540
|
parameters: [
|
514
541
|
create_opt_param("conditions", type: "T.untyped", default: ":none"),
|
515
542
|
],
|
@@ -518,7 +545,6 @@ module Tapioca
|
|
518
545
|
when :include?, :member?
|
519
546
|
create_common_method(
|
520
547
|
method_name,
|
521
|
-
common_relation_methods_module,
|
522
548
|
parameters: [
|
523
549
|
create_param("record", type: "T.untyped"),
|
524
550
|
],
|
@@ -527,7 +553,6 @@ module Tapioca
|
|
527
553
|
when :find
|
528
554
|
create_common_method(
|
529
555
|
"find",
|
530
|
-
common_relation_methods_module,
|
531
556
|
parameters: [
|
532
557
|
create_rest_param("args", type: "T.untyped"),
|
533
558
|
],
|
@@ -536,7 +561,6 @@ module Tapioca
|
|
536
561
|
when :find_by
|
537
562
|
create_common_method(
|
538
563
|
"find_by",
|
539
|
-
common_relation_methods_module,
|
540
564
|
parameters: [
|
541
565
|
create_rest_param("args", type: "T.untyped"),
|
542
566
|
],
|
@@ -545,7 +569,6 @@ module Tapioca
|
|
545
569
|
when :find_by!
|
546
570
|
create_common_method(
|
547
571
|
"find_by!",
|
548
|
-
common_relation_methods_module,
|
549
572
|
parameters: [
|
550
573
|
create_rest_param("args", type: "T.untyped"),
|
551
574
|
],
|
@@ -554,7 +577,6 @@ module Tapioca
|
|
554
577
|
when :find_sole_by
|
555
578
|
create_common_method(
|
556
579
|
"find_sole_by",
|
557
|
-
common_relation_methods_module,
|
558
580
|
parameters: [
|
559
581
|
create_param("arg", type: "T.untyped"),
|
560
582
|
create_rest_param("args", type: "T.untyped"),
|
@@ -564,14 +586,12 @@ module Tapioca
|
|
564
586
|
when :sole
|
565
587
|
create_common_method(
|
566
588
|
"sole",
|
567
|
-
common_relation_methods_module,
|
568
589
|
parameters: [],
|
569
590
|
return_type: constant_name,
|
570
591
|
)
|
571
592
|
when :first, :last, :take
|
572
593
|
create_common_method(
|
573
594
|
method_name,
|
574
|
-
common_relation_methods_module,
|
575
595
|
parameters: [
|
576
596
|
create_opt_param("limit", type: "T.untyped", default: "nil"),
|
577
597
|
],
|
@@ -588,7 +608,6 @@ module Tapioca
|
|
588
608
|
|
589
609
|
create_common_method(
|
590
610
|
method_name,
|
591
|
-
common_relation_methods_module,
|
592
611
|
return_type: return_type,
|
593
612
|
)
|
594
613
|
end
|
@@ -599,7 +618,6 @@ module Tapioca
|
|
599
618
|
when :find_signed
|
600
619
|
create_common_method(
|
601
620
|
"find_signed",
|
602
|
-
common_relation_methods_module,
|
603
621
|
parameters: [
|
604
622
|
create_param("signed_id", type: "T.untyped"),
|
605
623
|
create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
|
@@ -609,7 +627,6 @@ module Tapioca
|
|
609
627
|
when :find_signed!
|
610
628
|
create_common_method(
|
611
629
|
"find_signed!",
|
612
|
-
common_relation_methods_module,
|
613
630
|
parameters: [
|
614
631
|
create_param("signed_id", type: "T.untyped"),
|
615
632
|
create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
|
@@ -624,7 +641,6 @@ module Tapioca
|
|
624
641
|
when :average, :maximum, :minimum
|
625
642
|
create_common_method(
|
626
643
|
method_name,
|
627
|
-
common_relation_methods_module,
|
628
644
|
parameters: [
|
629
645
|
create_param("column_name", type: "T.any(String, Symbol)"),
|
630
646
|
],
|
@@ -633,7 +649,6 @@ module Tapioca
|
|
633
649
|
when :calculate
|
634
650
|
create_common_method(
|
635
651
|
"calculate",
|
636
|
-
common_relation_methods_module,
|
637
652
|
parameters: [
|
638
653
|
create_param("operation", type: "Symbol"),
|
639
654
|
create_param("column_name", type: "T.any(String, Symbol)"),
|
@@ -643,18 +658,16 @@ module Tapioca
|
|
643
658
|
when :count
|
644
659
|
create_common_method(
|
645
660
|
"count",
|
646
|
-
common_relation_methods_module,
|
647
661
|
parameters: [
|
648
662
|
create_opt_param("column_name", type: "T.untyped", default: "nil"),
|
649
663
|
],
|
650
664
|
return_type: "T.untyped",
|
651
665
|
)
|
652
666
|
when :ids
|
653
|
-
create_common_method("ids",
|
667
|
+
create_common_method("ids", return_type: "Array")
|
654
668
|
when :pick, :pluck
|
655
669
|
create_common_method(
|
656
670
|
method_name,
|
657
|
-
common_relation_methods_module,
|
658
671
|
parameters: [
|
659
672
|
create_rest_param("column_names", type: "T.untyped"),
|
660
673
|
],
|
@@ -663,7 +676,6 @@ module Tapioca
|
|
663
676
|
when :sum
|
664
677
|
create_common_method(
|
665
678
|
"sum",
|
666
|
-
common_relation_methods_module,
|
667
679
|
parameters: [
|
668
680
|
create_opt_param("column_name", type: "T.nilable(T.any(String, Symbol))", default: "nil"),
|
669
681
|
create_block_param("block", type: "T.nilable(T.proc.params(record: T.untyped).returns(T.untyped))"),
|
@@ -673,11 +685,63 @@ module Tapioca
|
|
673
685
|
end
|
674
686
|
end
|
675
687
|
|
688
|
+
BATCHES_METHODS.each do |method_name|
|
689
|
+
case method_name
|
690
|
+
when :find_each
|
691
|
+
order = ActiveRecord::Batches.instance_method(:find_each).parameters.include?([:key, :order])
|
692
|
+
create_common_method(
|
693
|
+
"find_each",
|
694
|
+
parameters: [
|
695
|
+
create_kw_opt_param("start", type: "T.untyped", default: "nil"),
|
696
|
+
create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
|
697
|
+
create_kw_opt_param("batch_size", type: "Integer", default: "1000"),
|
698
|
+
create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
|
699
|
+
*(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
|
700
|
+
create_block_param("block", type: "T.nilable(T.proc.params(object: #{constant_name}).void)"),
|
701
|
+
],
|
702
|
+
return_type: "T.nilable(T::Enumerator[#{constant_name}])",
|
703
|
+
)
|
704
|
+
when :find_in_batches
|
705
|
+
order = ActiveRecord::Batches.instance_method(:find_in_batches).parameters.include?([:key, :order])
|
706
|
+
create_common_method(
|
707
|
+
"find_in_batches",
|
708
|
+
parameters: [
|
709
|
+
create_kw_opt_param("start", type: "T.untyped", default: "nil"),
|
710
|
+
create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
|
711
|
+
create_kw_opt_param("batch_size", type: "Integer", default: "1000"),
|
712
|
+
create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
|
713
|
+
*(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
|
714
|
+
create_block_param(
|
715
|
+
"block",
|
716
|
+
type: "T.nilable(T.proc.params(object: T::Array[#{constant_name}]).void)",
|
717
|
+
),
|
718
|
+
],
|
719
|
+
return_type: "T.nilable(T::Enumerator[T::Enumerator[#{constant_name}]])",
|
720
|
+
)
|
721
|
+
when :in_batches
|
722
|
+
order = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :order])
|
723
|
+
use_ranges = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :use_ranges])
|
724
|
+
create_common_method(
|
725
|
+
"in_batches",
|
726
|
+
parameters: [
|
727
|
+
create_kw_opt_param("of", type: "Integer", default: "1000"),
|
728
|
+
create_kw_opt_param("start", type: "T.untyped", default: "nil"),
|
729
|
+
create_kw_opt_param("finish", type: "T.untyped", default: "nil"),
|
730
|
+
create_kw_opt_param("load", type: "T.untyped", default: "false"),
|
731
|
+
create_kw_opt_param("error_on_ignore", type: "T.untyped", default: "nil"),
|
732
|
+
*(create_kw_opt_param("order", type: "Symbol", default: ":asc") if order),
|
733
|
+
*(create_kw_opt_param("use_ranges", type: "T.untyped", default: "nil") if use_ranges),
|
734
|
+
create_block_param("block", type: "T.nilable(T.proc.params(object: #{RelationClassName}).void)"),
|
735
|
+
],
|
736
|
+
return_type: "T.nilable(::ActiveRecord::Batches::BatchEnumerator)",
|
737
|
+
)
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
676
741
|
ENUMERABLE_QUERY_METHODS.each do |method_name|
|
677
742
|
block_type = "T.nilable(T.proc.params(record: #{constant_name}).returns(T.untyped))"
|
678
743
|
create_common_method(
|
679
744
|
method_name,
|
680
|
-
common_relation_methods_module,
|
681
745
|
parameters: [
|
682
746
|
create_block_param("block", type: block_type),
|
683
747
|
],
|
@@ -689,7 +753,6 @@ module Tapioca
|
|
689
753
|
block_type = "T.nilable(T.proc.params(object: #{constant_name}).void)"
|
690
754
|
create_common_method(
|
691
755
|
method_name,
|
692
|
-
common_relation_methods_module,
|
693
756
|
parameters: [
|
694
757
|
create_param("attributes", type: "T.untyped"),
|
695
758
|
create_block_param("block", type: block_type),
|
@@ -701,7 +764,6 @@ module Tapioca
|
|
701
764
|
BUILDER_METHODS.each do |method_name|
|
702
765
|
create_common_method(
|
703
766
|
method_name,
|
704
|
-
common_relation_methods_module,
|
705
767
|
parameters: [
|
706
768
|
create_opt_param("attributes", type: "T.untyped", default: "nil"),
|
707
769
|
create_block_param("block", type: "T.nilable(T.proc.params(object: #{constant_name}).void)"),
|
@@ -714,12 +776,11 @@ module Tapioca
|
|
714
776
|
sig do
|
715
777
|
params(
|
716
778
|
name: T.any(Symbol, String),
|
717
|
-
common_relation_methods_module: RBI::Scope,
|
718
779
|
parameters: T::Array[RBI::TypedParam],
|
719
780
|
return_type: T.nilable(String),
|
720
781
|
).void
|
721
782
|
end
|
722
|
-
def create_common_method(name,
|
783
|
+
def create_common_method(name, parameters: [], return_type: nil)
|
723
784
|
common_relation_methods_module.create_method(
|
724
785
|
name.to_s,
|
725
786
|
parameters: parameters,
|
@@ -730,8 +791,6 @@ module Tapioca
|
|
730
791
|
sig do
|
731
792
|
params(
|
732
793
|
name: T.any(Symbol, String),
|
733
|
-
relation_methods_module: RBI::Scope,
|
734
|
-
association_relation_methods_module: RBI::Scope,
|
735
794
|
parameters: T::Array[RBI::TypedParam],
|
736
795
|
relation_return_type: String,
|
737
796
|
association_return_type: String,
|
@@ -739,8 +798,6 @@ module Tapioca
|
|
739
798
|
end
|
740
799
|
def create_relation_method(
|
741
800
|
name,
|
742
|
-
relation_methods_module,
|
743
|
-
association_relation_methods_module,
|
744
801
|
parameters: [],
|
745
802
|
relation_return_type: RelationClassName,
|
746
803
|
association_return_type: AssociationRelationClassName
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "active_record"
|
6
|
+
rescue LoadError
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
require "tapioca/dsl/helpers/active_record_constants_helper"
|
11
|
+
|
12
|
+
module Tapioca
|
13
|
+
module Dsl
|
14
|
+
module Compilers
|
15
|
+
# `Tapioca::Dsl::Compilers::ActiveModelSecurePassword` decorates RBI files for all
|
16
|
+
# classes that use [`ActiveRecord::SecureToken`](https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html).
|
17
|
+
#
|
18
|
+
# For example, with the following class:
|
19
|
+
#
|
20
|
+
# ~~~rb
|
21
|
+
# class User < ActiveRecord::Base
|
22
|
+
# has_secure_token
|
23
|
+
# has_secure_token :auth_token, length: 36
|
24
|
+
# end
|
25
|
+
# ~~~
|
26
|
+
#
|
27
|
+
# this compiler will produce an RBI file with the following content:
|
28
|
+
# ~~~rbi
|
29
|
+
# # typed: true
|
30
|
+
#
|
31
|
+
# class User
|
32
|
+
# sig { returns(T::Boolean) }
|
33
|
+
# def regenerate_token; end
|
34
|
+
#
|
35
|
+
# sig { returns(T::Boolean) }
|
36
|
+
# def regenerate_auth_token; end
|
37
|
+
# end
|
38
|
+
# ~~~
|
39
|
+
class ActiveRecordSecureToken < Compiler
|
40
|
+
extend T::Sig
|
41
|
+
include Helpers::ActiveRecordConstantsHelper
|
42
|
+
|
43
|
+
ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
|
44
|
+
|
45
|
+
sig { override.void }
|
46
|
+
def decorate
|
47
|
+
return if constant.__tapioca_secure_tokens.nil?
|
48
|
+
|
49
|
+
root.create_path(constant) do |model|
|
50
|
+
model.create_module(SecureTokensModuleName) do |mod|
|
51
|
+
constant.__tapioca_secure_tokens.each do |attribute|
|
52
|
+
mod.create_method(
|
53
|
+
"regenerate_#{attribute}",
|
54
|
+
return_type: "T::Boolean",
|
55
|
+
)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
model.create_include(SecureTokensModuleName)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class << self
|
64
|
+
extend T::Sig
|
65
|
+
|
66
|
+
sig { override.returns(T::Enumerable[Module]) }
|
67
|
+
def gather_constants
|
68
|
+
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -126,17 +126,20 @@ module Tapioca
|
|
126
126
|
|
127
127
|
private
|
128
128
|
|
129
|
-
TYPES = T.let(
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
129
|
+
TYPES = T.let(
|
130
|
+
{
|
131
|
+
boolean: "T::Boolean",
|
132
|
+
integer: "Integer",
|
133
|
+
string: "String",
|
134
|
+
float: "Float",
|
135
|
+
date: "Date",
|
136
|
+
time: "Time",
|
137
|
+
datetime: "DateTime",
|
138
|
+
decimal: "BigDecimal",
|
139
|
+
any: "T.untyped",
|
140
|
+
}.freeze,
|
141
|
+
T::Hash[Symbol, String],
|
142
|
+
)
|
140
143
|
|
141
144
|
sig { params(attr_type: Symbol).returns(String) }
|
142
145
|
def type_for(attr_type)
|
@@ -85,18 +85,21 @@ module Tapioca
|
|
85
85
|
|
86
86
|
private
|
87
87
|
|
88
|
-
TYPES = T.let(
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
88
|
+
TYPES = T.let(
|
89
|
+
{
|
90
|
+
boolean: "T::Boolean",
|
91
|
+
integer: "Integer",
|
92
|
+
string: "String",
|
93
|
+
float: "Float",
|
94
|
+
date: "Date",
|
95
|
+
time: "Time",
|
96
|
+
datetime: "DateTime",
|
97
|
+
decimal: "BigDecimal",
|
98
|
+
binary: "String",
|
99
|
+
text: "String",
|
100
|
+
}.freeze,
|
101
|
+
T::Hash[Symbol, String],
|
102
|
+
)
|
100
103
|
|
101
104
|
sig { params(attr_type: Symbol).returns(String) }
|
102
105
|
def type_for(attr_type)
|
@@ -109,9 +112,13 @@ module Tapioca
|
|
109
112
|
|
110
113
|
klass.create_method(attribute, return_type: return_type)
|
111
114
|
klass.create_method("#{attribute}?", return_type: "T::Boolean")
|
112
|
-
klass.create_method(
|
113
|
-
|
114
|
-
|
115
|
+
klass.create_method(
|
116
|
+
"#{attribute}=",
|
117
|
+
parameters: [
|
118
|
+
create_param("value", type: return_type),
|
119
|
+
],
|
120
|
+
return_type: return_type,
|
121
|
+
)
|
115
122
|
end
|
116
123
|
end
|
117
124
|
end
|
@@ -48,8 +48,10 @@ module Tapioca
|
|
48
48
|
|
49
49
|
ConstantType = type_member do
|
50
50
|
{
|
51
|
-
fixed: T.all(
|
52
|
-
|
51
|
+
fixed: T.all(
|
52
|
+
Module,
|
53
|
+
::ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods,
|
54
|
+
),
|
53
55
|
}
|
54
56
|
end
|
55
57
|
|