tapioca 0.10.4 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|