tapioca 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f93b130a7096e0712ccd91b8406d92ce537287afafc8aad7586e7f670d88a131
4
- data.tar.gz: b2cc1e6d2658002600c1edd9c5c88b22704e3f4170ff19aff93bb9fc21df688e
3
+ metadata.gz: 3a448cd511151879e4eef761b28cc8f5b1904f0d57e560a38af09bdda9689f98
4
+ data.tar.gz: 563c5e68f866444da629a4b206fed22b8a27531c36c0378d669886aa2a704eaf
5
5
  SHA512:
6
- metadata.gz: aa10ff7ffd4768cea802b63dc68273fa0abf7f69b61a83b1325669e97d706cb8afcc704093c93596a830662fe04b01ad2ded3c166abd69a5c69097bd28f586c9
7
- data.tar.gz: 63499428de9374990372beb46ece3f98d0f446ba28ef02bfa181179113e37e587ff9867bbe0d729d67c03ddb2813943f6f04d14f2065589a603a766a06ce8096
6
+ metadata.gz: c847afeb5c173ad8b0c46a0f2fd214336150124fd96f0c729029ce492a5f4aea4bf5d26adfd64cf386486f22342b21f502cdbc52c68ca544a65c4bf6777dacee
7
+ data.tar.gz: e25a62343cc4522d37e9508b4215f6efb9115b93e1e9ba38c71edf26da025126732b4762b834304d0e439c741d581f238e29e22dded9fcbf0415256041f8f849
@@ -49,7 +49,7 @@ module Tapioca
49
49
  sig { returns(T::Enumerable[T::Class[T.anything]]) }
50
50
  def all_classes
51
51
  @all_classes ||= T.let(
52
- T.cast(ObjectSpace.each_object(Class), T::Enumerable[T::Class[T.anything]]).each,
52
+ ObjectSpace.each_object(Class),
53
53
  T.nilable(T::Enumerable[T::Class[T.anything]]),
54
54
  )
55
55
  end
@@ -57,7 +57,7 @@ module Tapioca
57
57
  sig { returns(T::Enumerable[Module]) }
58
58
  def all_modules
59
59
  @all_modules ||= T.let(
60
- T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each,
60
+ ObjectSpace.each_object(Module),
61
61
  T.nilable(T::Enumerable[Module]),
62
62
  )
63
63
  end
@@ -147,7 +147,7 @@ module Tapioca
147
147
  machine.create_method(
148
148
  method,
149
149
  parameters: [
150
- create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"),
150
+ create_rest_param("callbacks", type: "T.any(String, Symbol, T::Class[T.anything], Proc)"),
151
151
  create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"),
152
152
  ],
153
153
  )
@@ -57,9 +57,7 @@ module Tapioca
57
57
  sig { override.returns(T::Enumerable[Module]) }
58
58
  def gather_constants
59
59
  # Collect all the classes that include ActiveModel::Validations
60
- all_classes.select do |c|
61
- c < ActiveModel::Validations
62
- end
60
+ all_classes.select { |c| ActiveModel::Validations > c }
63
61
  end
64
62
  end
65
63
 
@@ -188,6 +188,7 @@ module Tapioca
188
188
  def populate_single_assoc_getter_setter(klass, association_name, reflection)
189
189
  association_class = type_for(reflection)
190
190
  association_type = as_nilable_type(association_class)
191
+ association_methods_module = constant.generated_association_methods
191
192
 
192
193
  klass.create_method(
193
194
  association_name.to_s,
@@ -206,6 +207,18 @@ module Tapioca
206
207
  "reset_#{association_name}",
207
208
  return_type: "void",
208
209
  )
210
+ if association_methods_module.method_defined?("#{association_name}_changed?")
211
+ klass.create_method(
212
+ "#{association_name}_changed?",
213
+ return_type: "T::Boolean",
214
+ )
215
+ end
216
+ if association_methods_module.method_defined?("#{association_name}_previously_changed?")
217
+ klass.create_method(
218
+ "#{association_name}_previously_changed?",
219
+ return_type: "T::Boolean",
220
+ )
221
+ end
209
222
  unless reflection.polymorphic?
210
223
  klass.create_method(
211
224
  "build_#{association_name}",
@@ -111,7 +111,7 @@ module Tapioca
111
111
  sig { params(mod: RBI::Scope, name: String).void }
112
112
  def create_fixture_method(mod, name)
113
113
  return_type = return_type_for_fixture(name)
114
- mod << RBI::Method.new(name) do |node|
114
+ mod.create_method(name) do |node|
115
115
  node.add_opt_param("fixture_name", "nil")
116
116
  node.add_rest_param("other_fixtures")
117
117
 
@@ -155,6 +155,25 @@ module Tapioca
155
155
 
156
156
  ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
157
157
 
158
+ # From ActiveRecord::ConnectionAdapter::Quoting#quote, minus nil
159
+ ID_TYPES = T.let(
160
+ [
161
+ "String",
162
+ "Symbol",
163
+ "::ActiveSupport::Multibyte::Chars",
164
+ "T::Boolean",
165
+ "BigDecimal",
166
+ "Numeric",
167
+ "::ActiveRecord::Type::Binary::Data",
168
+ "::ActiveRecord::Type::Time::Value",
169
+ "Date",
170
+ "Time",
171
+ "::ActiveSupport::Duration",
172
+ "T::Class[T.anything]",
173
+ ].to_set.freeze,
174
+ T::Set[String],
175
+ )
176
+
158
177
  sig { override.void }
159
178
  def decorate
160
179
  create_classes_and_includes
@@ -220,7 +239,7 @@ module Tapioca
220
239
  [:find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :create_or_find_by, :create_or_find_by!],
221
240
  T::Array[Symbol],
222
241
  )
223
- BUILDER_METHODS = T.let([:new, :build, :create, :create!], T::Array[Symbol])
242
+ BUILDER_METHODS = T.let([:new, :create, :create!, :build], T::Array[Symbol])
224
243
  TO_ARRAY_METHODS = T.let([:to_ary, :to_a], T::Array[Symbol])
225
244
 
226
245
  private
@@ -663,58 +682,43 @@ module Tapioca
663
682
  return_type: "T::Boolean",
664
683
  )
665
684
  when :find
666
- # From ActiveRecord::ConnectionAdapter::Quoting#quote, minus nil
667
- id_types = [
668
- "String",
669
- "Symbol",
670
- "::ActiveSupport::Multibyte::Chars",
671
- "T::Boolean",
672
- "BigDecimal",
673
- "Numeric",
674
- "::ActiveRecord::Type::Binary::Data",
675
- "::ActiveRecord::Type::Time::Value",
676
- "Date",
677
- "Time",
678
- "::ActiveSupport::Duration",
679
- "T::Class[T.anything]",
680
- ].to_set
685
+ id_types = ID_TYPES
681
686
 
682
687
  if constant.table_exists?
683
688
  primary_key_type = constant.type_for_attribute(constant.primary_key)
684
689
  type = Tapioca::Dsl::Helpers::ActiveModelTypeHelper.type_for(primary_key_type)
685
690
  type = RBIHelper.as_non_nilable_type(type)
686
- id_types << type if type != "T.untyped"
691
+
692
+ id_types = ID_TYPES.union([type]) if type != "T.untyped"
687
693
  end
688
694
 
689
695
  id_types = "T.any(#{id_types.to_a.join(", ")})"
696
+ if constant.try(:composite_primary_key?)
697
+ id_types = "T::Array[#{id_types}]"
698
+ end
690
699
 
691
- array_type = if constant.try(:composite_primary_key?)
692
- "T::Array[T::Array[#{id_types}]]"
693
- else
694
- "T::Array[#{id_types}]"
700
+ array_type = "T::Array[#{id_types}]"
701
+
702
+ common_relation_methods_module.create_method("find") do |method|
703
+ method.add_opt_param("args", "nil")
704
+ method.add_block_param("block")
705
+
706
+ method.add_sig do |sig|
707
+ sig.add_param("args", id_types)
708
+ sig.return_type = constant_name
709
+ end
710
+
711
+ method.add_sig do |sig|
712
+ sig.add_param("args", array_type)
713
+ sig.return_type = "T::Enumerable[#{constant_name}]"
714
+ end
715
+
716
+ method.add_sig do |sig|
717
+ sig.add_param("args", "NilClass")
718
+ sig.add_param("block", "T.proc.params(object: #{constant_name}).void")
719
+ sig.return_type = as_nilable_type(constant_name)
720
+ end
695
721
  end
696
- sigs = [
697
- common_relation_methods_module.create_sig(
698
- parameters: { args: id_types },
699
- return_type: constant_name,
700
- ),
701
- common_relation_methods_module.create_sig(
702
- parameters: { args: array_type },
703
- return_type: "T::Enumerable[#{constant_name}]",
704
- ),
705
- common_relation_methods_module.create_sig(
706
- parameters: {
707
- args: "NilClass",
708
- block: "T.proc.params(object: #{constant_name}).void",
709
- },
710
- return_type: as_nilable_type(constant_name),
711
- ),
712
- ]
713
- common_relation_methods_module.create_method_with_sigs(
714
- "find",
715
- sigs: sigs,
716
- parameters: [RBI::OptParam.new("args", "nil"), RBI::BlockParam.new("block")],
717
- )
718
722
  when :find_by
719
723
  create_common_method(
720
724
  "find_by",
@@ -747,21 +751,18 @@ module Tapioca
747
751
  return_type: constant_name,
748
752
  )
749
753
  when :first, :last, :take
750
- sigs = [
751
- common_relation_methods_module.create_sig(
752
- parameters: { limit: "NilClass" },
753
- return_type: as_nilable_type(constant_name),
754
- ),
755
- common_relation_methods_module.create_sig(
756
- parameters: { limit: "Integer" },
757
- return_type: "T::Array[#{constant_name}]",
758
- ),
759
- ]
760
- common_relation_methods_module.create_method_with_sigs(
761
- method_name.to_s,
762
- sigs: sigs,
763
- parameters: [RBI::OptParam.new("limit", "nil")],
764
- )
754
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
755
+ method.add_opt_param("limit", "nil")
756
+
757
+ method.add_sig do |sig|
758
+ sig.return_type = as_nilable_type(constant_name)
759
+ end
760
+
761
+ method.add_sig do |sig|
762
+ sig.add_param("limit", "Integer")
763
+ sig.return_type = "T::Array[#{constant_name}]"
764
+ end
765
+ end
765
766
  when :raise_record_not_found_exception!
766
767
  # skip
767
768
  else
@@ -821,24 +822,21 @@ module Tapioca
821
822
  return_type: "T.any(Integer, Float, BigDecimal)",
822
823
  )
823
824
  when :count
824
- sigs = [
825
- common_relation_methods_module.create_sig(
826
- parameters: { column_name: "T.nilable(T.any(String, Symbol))" },
827
- return_type: "Integer",
828
- ),
829
- common_relation_methods_module.create_sig(
830
- parameters: { column_name: "NilClass", block: "T.proc.params(object: #{constant_name}).void" },
831
- return_type: "Integer",
832
- ),
833
- ]
834
- common_relation_methods_module.create_method_with_sigs(
835
- "count",
836
- sigs: sigs,
837
- parameters: [
838
- RBI::OptParam.new("column_name", "nil"),
839
- RBI::BlockParam.new("block"),
840
- ],
841
- )
825
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
826
+ method.add_opt_param("column_name", "nil")
827
+ method.add_block_param("block")
828
+
829
+ method.add_sig do |sig|
830
+ sig.add_param("column_name", "T.nilable(T.any(String, Symbol))")
831
+ sig.return_type = "Integer"
832
+ end
833
+
834
+ method.add_sig do |sig|
835
+ sig.add_param("column_name", "NilClass")
836
+ sig.add_param("block", "T.proc.params(object: #{constant_name}).void")
837
+ sig.return_type = "Integer"
838
+ end
839
+ end
842
840
  when :ids
843
841
  create_common_method("ids", return_type: "Array")
844
842
  when :pick, :pluck
@@ -850,29 +848,21 @@ module Tapioca
850
848
  return_type: "T.untyped",
851
849
  )
852
850
  when :sum
853
- sigs = [
854
- common_relation_methods_module.create_sig(
855
- parameters: { initial_value_or_column: "T.untyped" },
856
- return_type: "T.any(Integer, Float, BigDecimal)",
857
- ),
858
- common_relation_methods_module.create_sig(
859
- type_parameters: ["U"],
860
- parameters:
861
- {
862
- initial_value_or_column: "T.nilable(T.type_parameter(:U))",
863
- block: "T.proc.params(object: #{constant_name}).returns(T.type_parameter(:U))",
864
- },
865
- return_type: "T.type_parameter(:U)",
866
- ),
867
- ]
868
- common_relation_methods_module.create_method_with_sigs(
869
- method_name.to_s,
870
- sigs: sigs,
871
- parameters: [
872
- RBI::OptParam.new("initial_value_or_column", "nil"),
873
- RBI::BlockParam.new("block"),
874
- ],
875
- )
851
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
852
+ method.add_opt_param("initial_value_or_column", "nil")
853
+ method.add_block_param("block")
854
+
855
+ method.add_sig do |sig|
856
+ sig.add_param("initial_value_or_column", "T.untyped")
857
+ sig.return_type = "T.any(Integer, Float, BigDecimal)"
858
+ end
859
+
860
+ method.add_sig(type_params: ["U"]) do |sig|
861
+ sig.add_param("initial_value_or_column", "T.nilable(T.type_parameter(:U))")
862
+ sig.add_param("block", "T.proc.params(object: #{constant_name}).returns(T.type_parameter(:U))")
863
+ sig.return_type = "T.type_parameter(:U)"
864
+ end
865
+ end
876
866
  end
877
867
  end
878
868
 
@@ -880,102 +870,100 @@ module Tapioca
880
870
  case method_name
881
871
  when :find_each
882
872
  order = ActiveRecord::Batches.instance_method(:find_each).parameters.include?([:key, :order])
883
- parameters = {
884
- start: "T.untyped",
885
- finish: "T.untyped",
886
- batch_size: "Integer",
887
- error_on_ignore: "T.untyped",
888
- order: ("Symbol" if order),
889
- }.compact
890
- sigs = [
891
- common_relation_methods_module.create_sig(
892
- parameters: parameters.merge(block: "T.proc.params(object: #{constant_name}).void"),
893
- return_type: "void",
894
- ),
895
- common_relation_methods_module.create_sig(
896
- parameters: parameters,
897
- return_type: "T::Enumerator[#{constant_name}]",
898
- ),
899
- ]
900
- common_relation_methods_module.create_method_with_sigs(
901
- "find_each",
902
- sigs: sigs,
903
- parameters: [
904
- RBI::KwOptParam.new("start", "nil"),
905
- RBI::KwOptParam.new("finish", "nil"),
906
- RBI::KwOptParam.new("batch_size", "1000"),
907
- RBI::KwOptParam.new("error_on_ignore", "nil"),
908
- *(RBI::KwOptParam.new("order", ":asc") if order),
909
- RBI::BlockParam.new("block"),
910
- ],
911
- )
873
+
874
+ common_relation_methods_module.create_method("find_each") do |method|
875
+ method.add_kw_opt_param("start", "nil")
876
+ method.add_kw_opt_param("finish", "nil")
877
+ method.add_kw_opt_param("batch_size", "1000")
878
+ method.add_kw_opt_param("error_on_ignore", "nil")
879
+ method.add_kw_opt_param("order", ":asc") if order
880
+ method.add_block_param("block")
881
+
882
+ method.add_sig do |sig|
883
+ sig.add_param("start", "T.untyped")
884
+ sig.add_param("finish", "T.untyped")
885
+ sig.add_param("batch_size", "Integer")
886
+ sig.add_param("error_on_ignore", "T.untyped")
887
+ sig.add_param("order", "Symbol") if order
888
+ sig.add_param("block", "T.proc.params(object: #{constant_name}).void")
889
+ sig.return_type = "void"
890
+ end
891
+
892
+ method.add_sig do |sig|
893
+ sig.add_param("start", "T.untyped")
894
+ sig.add_param("finish", "T.untyped")
895
+ sig.add_param("batch_size", "Integer")
896
+ sig.add_param("error_on_ignore", "T.untyped")
897
+ sig.add_param("order", "Symbol") if order
898
+ sig.return_type = "T::Enumerator[#{constant_name}]"
899
+ end
900
+ end
912
901
  when :find_in_batches
913
902
  order = ActiveRecord::Batches.instance_method(:find_in_batches).parameters.include?([:key, :order])
914
- parameters = {
915
- start: "T.untyped",
916
- finish: "T.untyped",
917
- batch_size: "Integer",
918
- error_on_ignore: "T.untyped",
919
- order: ("Symbol" if order),
920
- }.compact
921
- sigs = [
922
- common_relation_methods_module.create_sig(
923
- parameters: parameters.merge(block: "T.proc.params(object: T::Array[#{constant_name}]).void"),
924
- return_type: "void",
925
- ),
926
- common_relation_methods_module.create_sig(
927
- parameters: parameters,
928
- return_type: "T::Enumerator[T::Enumerator[#{constant_name}]]",
929
- ),
930
- ]
931
- common_relation_methods_module.create_method_with_sigs(
932
- "find_in_batches",
933
- sigs: sigs,
934
- parameters: [
935
- RBI::KwOptParam.new("start", "nil"),
936
- RBI::KwOptParam.new("finish", "nil"),
937
- RBI::KwOptParam.new("batch_size", "1000"),
938
- RBI::KwOptParam.new("error_on_ignore", "nil"),
939
- *(RBI::KwOptParam.new("order", ":asc") if order),
940
- RBI::BlockParam.new("block"),
941
- ],
942
- )
903
+ common_relation_methods_module.create_method("find_in_batches") do |method|
904
+ method.add_kw_opt_param("start", "nil")
905
+ method.add_kw_opt_param("finish", "nil")
906
+ method.add_kw_opt_param("batch_size", "1000")
907
+ method.add_kw_opt_param("error_on_ignore", "nil")
908
+ method.add_kw_opt_param("order", ":asc") if order
909
+ method.add_block_param("block")
910
+
911
+ method.add_sig do |sig|
912
+ sig.add_param("start", "T.untyped")
913
+ sig.add_param("finish", "T.untyped")
914
+ sig.add_param("batch_size", "Integer")
915
+ sig.add_param("error_on_ignore", "T.untyped")
916
+ sig.add_param("order", "Symbol") if order
917
+ sig.add_param("block", "T.proc.params(object: T::Array[#{constant_name}]).void")
918
+ sig.return_type = "void"
919
+ end
920
+
921
+ method.add_sig do |sig|
922
+ sig.add_param("start", "T.untyped")
923
+ sig.add_param("finish", "T.untyped")
924
+ sig.add_param("batch_size", "Integer")
925
+ sig.add_param("error_on_ignore", "T.untyped")
926
+ sig.add_param("order", "Symbol") if order
927
+ sig.return_type = "T::Enumerator[T::Enumerator[#{constant_name}]]"
928
+ end
929
+ end
943
930
  when :in_batches
944
931
  order = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :order])
945
932
  use_ranges = ActiveRecord::Batches.instance_method(:in_batches).parameters.include?([:key, :use_ranges])
946
- parameters = {
947
- of: "Integer",
948
- start: "T.untyped",
949
- finish: "T.untyped",
950
- load: "T.untyped",
951
- error_on_ignore: "T.untyped",
952
- order: ("Symbol" if order),
953
- use_ranges: ("T.untyped" if use_ranges),
954
- }.compact
955
- sigs = [
956
- common_relation_methods_module.create_sig(
957
- parameters: parameters.merge(block: "T.proc.params(object: #{RelationClassName}).void"),
958
- return_type: "void",
959
- ),
960
- common_relation_methods_module.create_sig(
961
- parameters: parameters,
962
- return_type: "::ActiveRecord::Batches::BatchEnumerator",
963
- ),
964
- ]
965
- common_relation_methods_module.create_method_with_sigs(
966
- "in_batches",
967
- sigs: sigs,
968
- parameters: [
969
- RBI::KwOptParam.new("of", "1000"),
970
- RBI::KwOptParam.new("start", "nil"),
971
- RBI::KwOptParam.new("finish", "nil"),
972
- RBI::KwOptParam.new("load", "false"),
973
- RBI::KwOptParam.new("error_on_ignore", "nil"),
974
- *(RBI::KwOptParam.new("order", ":asc") if order),
975
- *(RBI::KwOptParam.new("use_ranges", "nil") if use_ranges),
976
- RBI::BlockParam.new("block"),
977
- ],
978
- )
933
+
934
+ common_relation_methods_module.create_method("in_batches") do |method|
935
+ method.add_kw_opt_param("of", "1000")
936
+ method.add_kw_opt_param("start", "nil")
937
+ method.add_kw_opt_param("finish", "nil")
938
+ method.add_kw_opt_param("load", "false")
939
+ method.add_kw_opt_param("error_on_ignore", "nil")
940
+ method.add_kw_opt_param("order", ":asc") if order
941
+ method.add_kw_opt_param("use_ranges", "nil") if use_ranges
942
+ method.add_block_param("block")
943
+
944
+ method.add_sig do |sig|
945
+ sig.add_param("of", "Integer")
946
+ sig.add_param("start", "T.untyped")
947
+ sig.add_param("finish", "T.untyped")
948
+ sig.add_param("load", "T.untyped")
949
+ sig.add_param("error_on_ignore", "T.untyped")
950
+ sig.add_param("order", "Symbol") if order
951
+ sig.add_param("use_ranges", "T.untyped") if use_ranges
952
+ sig.add_param("block", "T.proc.params(object: #{RelationClassName}).void")
953
+ sig.return_type = "void"
954
+ end
955
+
956
+ method.add_sig do |sig|
957
+ sig.add_param("of", "Integer")
958
+ sig.add_param("start", "T.untyped")
959
+ sig.add_param("finish", "T.untyped")
960
+ sig.add_param("load", "T.untyped")
961
+ sig.add_param("error_on_ignore", "T.untyped")
962
+ sig.add_param("order", "Symbol") if order
963
+ sig.add_param("use_ranges", "T.untyped") if use_ranges
964
+ sig.return_type = "::ActiveRecord::Batches::BatchEnumerator"
965
+ end
966
+ end
979
967
  end
980
968
  end
981
969
 
@@ -991,26 +979,50 @@ module Tapioca
991
979
  end
992
980
 
993
981
  FIND_OR_CREATE_METHODS.each do |method_name|
994
- block_type = "T.nilable(T.proc.params(object: #{constant_name}).void)"
995
- create_common_method(
996
- method_name,
997
- parameters: [
998
- create_param("attributes", type: "T.untyped"),
999
- create_block_param("block", type: block_type),
1000
- ],
1001
- return_type: constant_name,
1002
- )
982
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
983
+ method.add_param("attributes")
984
+ method.add_block_param("block")
985
+
986
+ # `T.untyped` matches `T::Array[T.untyped]` so the array signature
987
+ # must be defined first for Sorbet to pick it, if valid.
988
+ method.add_sig do |sig|
989
+ sig.add_param("attributes", "T::Array[T.untyped]")
990
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
991
+ sig.return_type = "T::Array[#{constant_name}]"
992
+ end
993
+
994
+ method.add_sig do |sig|
995
+ sig.add_param("attributes", "T.untyped")
996
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
997
+ sig.return_type = constant_name
998
+ end
999
+ end
1003
1000
  end
1004
1001
 
1005
1002
  BUILDER_METHODS.each do |method_name|
1006
- create_common_method(
1007
- method_name,
1008
- parameters: [
1009
- create_opt_param("attributes", type: "T.untyped", default: "nil"),
1010
- create_block_param("block", type: "T.nilable(T.proc.params(object: #{constant_name}).void)"),
1011
- ],
1012
- return_type: constant_name,
1013
- )
1003
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
1004
+ method.add_opt_param("attributes", "nil")
1005
+ method.add_block_param("block")
1006
+
1007
+ method.add_sig do |sig|
1008
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
1009
+ sig.return_type = constant_name
1010
+ end
1011
+
1012
+ # `T.untyped` matches `T::Array[T.untyped]` so the array signature
1013
+ # must be defined first for Sorbet to pick it, if valid.
1014
+ method.add_sig do |sig|
1015
+ sig.add_param("attributes", "T::Array[T.untyped]")
1016
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
1017
+ sig.return_type = "T::Array[#{constant_name}]"
1018
+ end
1019
+
1020
+ method.add_sig do |sig|
1021
+ sig.add_param("attributes", "T.untyped")
1022
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
1023
+ sig.return_type = constant_name
1024
+ end
1025
+ end
1014
1026
  end
1015
1027
  end
1016
1028
 
@@ -66,19 +66,18 @@ module Tapioca
66
66
 
67
67
  sig { override.returns(T::Enumerable[Module]) }
68
68
  def gather_constants
69
- # Find all Modules that are:
70
69
  all_modules.select do |mod|
71
- # named (i.e. not anonymous)
72
- name_of(mod) &&
73
- # not singleton classes
70
+ name_of(mod) && # i.e. not anonymous
74
71
  !mod.singleton_class? &&
75
- # extend ActiveSupport::Concern, and
76
- mod.singleton_class < ActiveSupport::Concern &&
77
- # have dependencies (i.e. include another concern)
78
- !dependencies_of(mod).empty?
72
+ ActiveSupport::Concern > mod.singleton_class &&
73
+ has_dependencies?(mod)
79
74
  end
80
75
  end
81
76
 
77
+ # Returns true when `mod` includes other concerns
78
+ sig { params(mod: Module).returns(T::Boolean) }
79
+ def has_dependencies?(mod) = dependencies_of(mod).any?
80
+
82
81
  sig { params(concern: Module).returns(T::Array[Module]) }
83
82
  def dependencies_of(concern)
84
83
  concern.instance_variable_get(:@_dependencies) || []
@@ -0,0 +1,68 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ return unless defined?(Time.current) && defined?(ActiveSupport::TimeWithZone)
5
+
6
+ module Tapioca
7
+ module Dsl
8
+ module Compilers
9
+ # `Tapioca::Dsl::Compilers::ActiveSupportTimeExt` generates an RBI file for the `Time#current` method
10
+ # defined by [Active Support's Time extensions](https://api.rubyonrails.org/classes/Time.html).
11
+ #
12
+ # If `Time.zone` or `config.time_zone` are set, then the `Time.current` method will be defined as returning
13
+ # an instance of `ActiveSupport::TimeWithZone`, otherwise it will return an instance of `Time`.
14
+ #
15
+ # For an application that is configured with:
16
+ # ```ruby
17
+ # config.time_zone = "UTC"
18
+ # ```
19
+ # this compiler will produce the following RBI file:
20
+ # ```rbi
21
+ # class Time
22
+ # class << self
23
+ # sig { returns(::ActiveSupport::TimeWithZone) }
24
+ # def current; end
25
+ # end
26
+ # end
27
+ # ```
28
+ # whereas if `Time.zone` and `config.time_zone` are not set, it will produce:
29
+ # ```rbi
30
+ # class Time
31
+ # class << self
32
+ # sig { returns(::Time) }
33
+ # def current; end
34
+ # end
35
+ # end
36
+ # ```
37
+ class ActiveSupportTimeExt < Compiler
38
+ extend T::Sig
39
+
40
+ ConstantType = type_member { { fixed: T.class_of(::Time) } }
41
+
42
+ sig { override.void }
43
+ def decorate
44
+ return unless constant.respond_to?(:zone)
45
+
46
+ root.create_path(constant) do |mod|
47
+ return_type = if ::Time.zone
48
+ "::ActiveSupport::TimeWithZone"
49
+ else
50
+ "::Time"
51
+ end
52
+
53
+ mod.create_method("current", return_type: return_type, class_method: true)
54
+ end
55
+ end
56
+
57
+ class << self
58
+ extend T::Sig
59
+
60
+ sig { override.returns(T::Enumerable[Module]) }
61
+ def gather_constants
62
+ [::Time]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -80,7 +80,7 @@ module Tapioca
80
80
 
81
81
  sig { override.returns(T::Enumerable[Module]) }
82
82
  def gather_constants
83
- all_classes.select { |c| c < GraphQL::Schema::InputObject }
83
+ all_classes.select { |c| GraphQL::Schema::InputObject > c }
84
84
  end
85
85
  end
86
86
  end
@@ -80,7 +80,7 @@ module Tapioca
80
80
 
81
81
  sig { override.returns(T::Enumerable[Module]) }
82
82
  def gather_constants
83
- all_classes.select { |c| c < GraphQL::Schema::Mutation && c != GraphQL::Schema::RelayClassicMutation }
83
+ all_classes.select { |c| GraphQL::Schema::Mutation > c && GraphQL::Schema::RelayClassicMutation != c }
84
84
  end
85
85
  end
86
86
  end
@@ -100,7 +100,7 @@ module Tapioca
100
100
  sig { override.returns(T::Enumerable[Module]) }
101
101
  def gather_constants
102
102
  descendants_of(::ActiveRecord::Base).select do |klass|
103
- klass < ::IdentityCache::WithoutPrimaryIndex
103
+ ::IdentityCache::WithoutPrimaryIndex > klass
104
104
  end
105
105
  end
106
106
  end
@@ -111,7 +111,7 @@ module Tapioca
111
111
  sig { override.returns(T::Enumerable[Module]) }
112
112
  def gather_constants
113
113
  all_modules.select do |c|
114
- name_of(c) && c < ::JsonApiClient::Resource
114
+ name_of(c) && ::JsonApiClient::Resource > c
115
115
  end
116
116
  end
117
117
  end
@@ -159,9 +159,7 @@ module Tapioca
159
159
  def gather_constants
160
160
  marker = Google::Protobuf::MessageExts::ClassMethods
161
161
 
162
- enum_modules = ObjectSpace.each_object(Google::Protobuf::EnumDescriptor).map do |desc|
163
- T.cast(desc, Google::Protobuf::EnumDescriptor).enummodule
164
- end
162
+ enum_modules = ObjectSpace.each_object(Google::Protobuf::EnumDescriptor).map(&:enummodule)
165
163
 
166
164
  results = if Google::Protobuf.const_defined?(:AbstractMessage)
167
165
  abstract_message_const = ::Google::Protobuf.const_get(:AbstractMessage)
@@ -73,7 +73,7 @@ module Tapioca
73
73
 
74
74
  sig { override.returns(T::Enumerable[Module]) }
75
75
  def gather_constants
76
- all_classes.select { |c| c < Sidekiq::Worker }
76
+ all_classes.select { |c| Sidekiq::Worker > c }
77
77
  end
78
78
  end
79
79
 
@@ -86,8 +86,9 @@ module Tapioca
86
86
  def gather_constants
87
87
  all_modules.select do |c|
88
88
  name_of(c) &&
89
- c != ::SmartProperties::Validations::Ancestor &&
90
- c < ::SmartProperties && ::SmartProperties::ClassMethods === c
89
+ ::SmartProperties > c &&
90
+ ::SmartProperties::Validations::Ancestor != c &&
91
+ ::SmartProperties::ClassMethods === c
91
92
  end
92
93
  end
93
94
  end
@@ -159,7 +159,7 @@ module Tapioca
159
159
 
160
160
  sig { override.returns(T::Enumerable[Module]) }
161
161
  def gather_constants
162
- all_classes.select { |mod| mod < ::StateMachines::InstanceMethods }
162
+ all_classes.select { |mod| ::StateMachines::InstanceMethods > mod }
163
163
  end
164
164
  end
165
165
 
@@ -231,12 +231,12 @@ module Tapioca
231
231
  instance_module.create_method(
232
232
  attribute,
233
233
  return_type: state_type,
234
- )
234
+ ) if ::StateMachines::HelperModule === machine.owner_class.instance_method(attribute).owner
235
235
  instance_module.create_method(
236
236
  "#{attribute}=",
237
237
  parameters: [create_param("value", type: state_type)],
238
238
  return_type: state_type,
239
- )
239
+ ) if ::StateMachines::HelperModule === machine.owner_class.instance_method("#{attribute}=").owner
240
240
  end
241
241
 
242
242
  sig { params(instance_module: RBI::Module, machine: ::StateMachines::Machine).void }
@@ -106,19 +106,28 @@ module Tapioca
106
106
  routes_reloader = Rails.application.routes_reloader
107
107
  routes_reloader.execute_unless_loaded if routes_reloader&.respond_to?(:execute_unless_loaded)
108
108
 
109
- Object.const_set(:GeneratedUrlHelpersModule, Rails.application.routes.named_routes.url_helpers_module)
110
- Object.const_set(:GeneratedPathHelpersModule, Rails.application.routes.named_routes.path_helpers_module)
109
+ url_helpers_module = Rails.application.routes.named_routes.url_helpers_module
110
+ path_helpers_module = Rails.application.routes.named_routes.path_helpers_module
111
+
112
+ Object.const_set(:GeneratedUrlHelpersModule, url_helpers_module)
113
+ Object.const_set(:GeneratedPathHelpersModule, path_helpers_module)
111
114
 
112
115
  constants = all_modules.select do |mod|
113
116
  next unless name_of(mod)
114
117
 
115
- includes_helper?(mod, GeneratedUrlHelpersModule) ||
116
- includes_helper?(mod, GeneratedPathHelpersModule) ||
117
- includes_helper?(mod.singleton_class, GeneratedUrlHelpersModule) ||
118
- includes_helper?(mod.singleton_class, GeneratedPathHelpersModule)
118
+ # Fast-path to quickly disqualify most cases
119
+ next false unless url_helpers_module > mod || # rubocop:disable Style/InvertibleUnlessCondition
120
+ path_helpers_module > mod ||
121
+ url_helpers_module > mod.singleton_class ||
122
+ path_helpers_module > mod.singleton_class
123
+
124
+ includes_helper?(mod, url_helpers_module) ||
125
+ includes_helper?(mod, path_helpers_module) ||
126
+ includes_helper?(mod.singleton_class, url_helpers_module) ||
127
+ includes_helper?(mod.singleton_class, path_helpers_module)
119
128
  end
120
129
 
121
- constants.concat(NON_DISCOVERABLE_INCLUDERS)
130
+ constants.concat(NON_DISCOVERABLE_INCLUDERS).push(GeneratedUrlHelpersModule, GeneratedPathHelpersModule)
122
131
  end
123
132
 
124
133
  sig { returns(T::Array[Module]) }
@@ -134,17 +143,20 @@ module Tapioca
134
143
  end.freeze
135
144
  end
136
145
 
146
+ # Returns `true` if `mod` "directly" includes `helper`.
147
+ # For classes, this method will return false if the `helper` is included only by a superclass
137
148
  sig { params(mod: Module, helper: Module).returns(T::Boolean) }
138
149
  private def includes_helper?(mod, helper)
139
- superclass_ancestors = []
150
+ ancestors = ancestors_of(mod)
140
151
 
141
- if Class === mod
142
- superclass = superclass_of(mod)
143
- superclass_ancestors = ancestors_of(superclass) if superclass
152
+ own_ancestors = if Class === mod && (superclass = superclass_of(mod))
153
+ # These ancestors are unique to `mod`, and exclude those in common with `superclass`.
154
+ ancestors.take(ancestors.count - ancestors_of(superclass).size)
155
+ else
156
+ ancestors
144
157
  end
145
158
 
146
- ancestors = Set.new.compare_by_identity.merge(ancestors_of(mod)).subtract(superclass_ancestors)
147
- ancestors.any? { |ancestor| helper == ancestor }
159
+ own_ancestors.include?(helper)
148
160
  end
149
161
  end
150
162
 
@@ -104,7 +104,7 @@ module Tapioca
104
104
 
105
105
  column = @constant.columns_hash[column_name]
106
106
  column_type = @constant.attribute_types[column_name]
107
- getter_type = type_for_activerecord_value(column_type)
107
+ getter_type = type_for_activerecord_value(column_type, column_nullability: !!column&.null)
108
108
  setter_type =
109
109
  case column_type
110
110
  when ActiveRecord::Enum::EnumType
@@ -121,8 +121,8 @@ module Tapioca
121
121
  end
122
122
  end
123
123
 
124
- sig { params(column_type: T.untyped).returns(String) }
125
- def type_for_activerecord_value(column_type)
124
+ sig { params(column_type: T.untyped, column_nullability: T::Boolean).returns(String) }
125
+ def type_for_activerecord_value(column_type, column_nullability:)
126
126
  case column_type
127
127
  when ->(type) { defined?(MoneyColumn) && MoneyColumn::ActiveRecordType === type }
128
128
  "::Money"
@@ -133,11 +133,12 @@ module Tapioca
133
133
  }
134
134
  # Reflect to see if `ActiveModel::Type::Value` is being used first.
135
135
  getter_type = Tapioca::Dsl::Helpers::ActiveModelTypeHelper.type_for(column_type)
136
- return getter_type unless getter_type == "T.untyped"
137
136
 
138
- # Otherwise fallback to String as `ActiveRecord::Encryption::EncryptedAttributeType` inherits from
137
+ # Fallback to String as `ActiveRecord::Encryption::EncryptedAttributeType` inherits from
139
138
  # `ActiveRecord::Type::Text` which inherits from `ActiveModel::Type::String`.
140
- "::String"
139
+ return "::String" if getter_type == "T.untyped"
140
+
141
+ as_non_nilable_if_persisted_and_not_nullable(getter_type, column_nullability:)
141
142
  when ActiveRecord::Type::String
142
143
  "::String"
143
144
  when ActiveRecord::Type::Date
@@ -160,7 +161,7 @@ module Tapioca
160
161
  defined?(ActiveRecord::Normalization::NormalizedValueType) &&
161
162
  ActiveRecord::Normalization::NormalizedValueType === type
162
163
  }
163
- type_for_activerecord_value(column_type.cast_type)
164
+ type_for_activerecord_value(column_type.cast_type, column_nullability:)
164
165
  when ->(type) {
165
166
  defined?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Uuid) &&
166
167
  ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Uuid === type
@@ -180,12 +181,25 @@ module Tapioca
180
181
  defined?(ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array) &&
181
182
  ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array === type
182
183
  }
183
- "T::Array[#{type_for_activerecord_value(column_type.subtype)}]"
184
+ "T::Array[#{type_for_activerecord_value(column_type.subtype, column_nullability:)}]"
184
185
  else
185
- ActiveModelTypeHelper.type_for(column_type)
186
+ as_non_nilable_if_persisted_and_not_nullable(
187
+ ActiveModelTypeHelper.type_for(column_type),
188
+ column_nullability: column_nullability,
189
+ )
186
190
  end
187
191
  end
188
192
 
193
+ sig { params(base_type: String, column_nullability: T::Boolean).returns(String) }
194
+ def as_non_nilable_if_persisted_and_not_nullable(base_type, column_nullability:)
195
+ # It's possible that when ActiveModel::Type::Value is used, the signature being reflected on in
196
+ # ActiveModelTypeHelper.type_for(type_value) may say the type can be nilable. However, if the type is
197
+ # persisted and the column is not nullable, we can assume it's not nilable.
198
+ return as_non_nilable_type(base_type) if @column_type_option.persisted? && !column_nullability
199
+
200
+ base_type
201
+ end
202
+
189
203
  sig { params(column_type: ActiveRecord::Enum::EnumType).returns(String) }
190
204
  def enum_setter_type(column_type)
191
205
  # In Rails < 7 this method is private. When support for that is dropped we can call the method directly
@@ -1,6 +1,7 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "tapioca/dsl"
4
5
  require "tapioca/helpers/test/content"
5
6
  require "tapioca/helpers/test/isolation"
6
7
  require "tapioca/helpers/test/template"
@@ -19,24 +19,24 @@ require "netrc"
19
19
  require "parallel"
20
20
  require "pathname"
21
21
  require "shellwords"
22
- require "spoom"
23
22
  require "tempfile"
24
23
  require "thor"
25
24
  require "yaml"
26
25
  require "yard-sorbet"
27
26
 
28
27
  require "tapioca/runtime/dynamic_mixin_compiler"
29
- require "tapioca/helpers/gem_helper"
30
-
31
- require "tapioca/helpers/git_attributes"
32
- require "tapioca/helpers/sorbet_helper"
33
- require "tapioca/helpers/rbi_helper"
34
28
  require "tapioca/sorbet_ext/backcompat_patches"
35
29
  require "tapioca/sorbet_ext/name_patch"
36
30
  require "tapioca/sorbet_ext/generic_name_patch"
37
31
  require "tapioca/sorbet_ext/proc_bind_patch"
38
32
  require "tapioca/runtime/generic_type_registry"
39
33
 
34
+ require "spoom"
35
+ require "tapioca/helpers/gem_helper"
36
+ require "tapioca/helpers/git_attributes"
37
+ require "tapioca/helpers/sorbet_helper"
38
+ require "tapioca/helpers/rbi_helper"
39
+
40
40
  require "tapioca/helpers/source_uri"
41
41
  require "tapioca/helpers/cli_helper"
42
42
  require "tapioca/helpers/config_helper"
@@ -63,10 +63,17 @@ module Tapioca
63
63
  def load_dsl_compilers
64
64
  say("Loading DSL compiler classes... ")
65
65
 
66
+ # Load all built-in compilers
67
+ Dir.glob("#{Tapioca::LIB_ROOT_DIR}/tapioca/dsl/compilers/*.rb").each do |compiler|
68
+ require File.expand_path(compiler)
69
+ end
70
+
71
+ # Load all custom compilers exported from gems
66
72
  ::Gem.find_files("tapioca/dsl/compilers/*.rb").each do |compiler|
67
73
  require File.expand_path(compiler)
68
74
  end
69
75
 
76
+ # Load all custom compilers from the project
70
77
  Dir.glob([
71
78
  "#{@tapioca_path}/generators/**/*.rb", # TODO: Here for backcompat, remove later
72
79
  "#{@tapioca_path}/compilers/**/*.rb",
@@ -47,12 +47,23 @@ module Tapioca
47
47
  ).void
48
48
  end
49
49
  def load_rails_application(environment_load: false, eager_load: false, app_root: ".", halt_upon_load_error: true)
50
- return unless File.exist?("#{app_root}/config/application.rb")
50
+ return unless File.exist?(File.expand_path("config/application.rb", app_root))
51
51
 
52
- if environment_load
53
- require "./#{app_root}/config/environment"
52
+ load_path = if environment_load
53
+ "config/environment"
54
54
  else
55
- require "./#{app_root}/config/application"
55
+ "config/application"
56
+ end
57
+
58
+ require File.expand_path(load_path, app_root)
59
+
60
+ unless defined?(Rails)
61
+ say(
62
+ "\nTried to load the app from `#{load_path}` as a Rails application " \
63
+ "but the `Rails` constant wasn't defined after loading the file.",
64
+ :yellow,
65
+ )
66
+ return
56
67
  end
57
68
 
58
69
  eager_load_rails_app if eager_load
@@ -80,65 +80,38 @@ module RBI
80
80
  params(
81
81
  name: String,
82
82
  parameters: T::Array[TypedParam],
83
- return_type: String,
83
+ return_type: T.nilable(String),
84
84
  class_method: T::Boolean,
85
85
  visibility: RBI::Visibility,
86
86
  comments: T::Array[RBI::Comment],
87
+ block: T.nilable(T.proc.params(node: RBI::Method).void),
87
88
  ).void
88
89
  end
89
- def create_method(name, parameters: [], return_type: "T.untyped", class_method: false, visibility: RBI::Public.new,
90
- comments: [])
91
- sig_params = parameters.to_h { |param| [param.param.name, param.type] }
92
- sig = create_sig(parameters: sig_params, return_type: return_type)
93
- create_method_with_sigs(
94
- name,
95
- sigs: [sig],
96
- parameters: parameters.map(&:param),
97
- class_method: class_method,
98
- visibility: visibility,
99
- comments: comments,
100
- )
101
- end
102
-
103
- sig do
104
- params(
105
- name: String,
106
- sigs: T::Array[RBI::Sig],
107
- parameters: T::Array[RBI::Param],
108
- class_method: T::Boolean,
109
- visibility: RBI::Visibility,
110
- comments: T::Array[RBI::Comment],
111
- ).void
112
- end
113
- def create_method_with_sigs(name, sigs:, parameters: [], class_method: false, visibility: RBI::Public.new,
114
- comments: [])
90
+ def create_method(name, parameters: [], return_type: nil, class_method: false, visibility: RBI::Public.new,
91
+ comments: [], &block)
115
92
  return unless Tapioca::RBIHelper.valid_method_name?(name)
116
93
 
94
+ sigs = []
95
+
96
+ if !block || !parameters.empty? || return_type
97
+ # If there is no block, and the params and return type have not been supplied, then
98
+ # we create a single signature with the given parameters and return type
99
+ params = parameters.map { |param| RBI::SigParam.new(param.param.name.to_s, param.type) }
100
+ sigs << RBI::Sig.new(params: params, return_type: return_type || "T.untyped")
101
+ end
102
+
117
103
  method = RBI::Method.new(
118
104
  name,
119
105
  sigs: sigs,
120
- params: parameters,
106
+ params: parameters.map(&:param),
121
107
  is_singleton: class_method,
122
108
  visibility: visibility,
123
109
  comments: comments,
110
+ &block
124
111
  )
125
112
  self << method
126
113
  end
127
114
 
128
- sig do
129
- params(
130
- parameters: T::Hash[T.any(String, Symbol), String],
131
- type_parameters: T::Array[String],
132
- return_type: String,
133
- ).returns(RBI::Sig)
134
- end
135
- def create_sig(parameters:, type_parameters: [], return_type: "T.untyped")
136
- params = parameters.map do |name, type|
137
- RBI::SigParam.new(name.to_s, type)
138
- end
139
- RBI::Sig.new(type_params: type_parameters, params: params, return_type: return_type)
140
- end
141
-
142
115
  private
143
116
 
144
117
  sig { returns(T::Hash[String, RBI::Node]) }
@@ -166,7 +166,7 @@ module Tapioca
166
166
  end
167
167
  def descendants_of(klass)
168
168
  result = ObjectSpace.each_object(klass.singleton_class).reject do |k|
169
- T.cast(k, Module).singleton_class? || T.unsafe(k) == klass
169
+ k.singleton_class? || k == klass
170
170
  end
171
171
 
172
172
  T.unsafe(result)
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.15.0"
5
+ VERSION = "0.16.0"
6
6
  end
data/lib/tapioca.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "sorbet-runtime"
5
+ require "rubygems/user_interaction"
5
6
 
6
7
  module Tapioca
7
8
  extend T::Sig
@@ -29,6 +30,7 @@ module Tapioca
29
30
 
30
31
  class Error < StandardError; end
31
32
 
33
+ LIB_ROOT_DIR = T.let(T.must(__dir__), String)
32
34
  SORBET_DIR = T.let("sorbet", String)
33
35
  SORBET_CONFIG_FILE = T.let("#{SORBET_DIR}/config", String)
34
36
  TAPIOCA_DIR = T.let("#{SORBET_DIR}/tapioca", String)
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
8
8
  - Alan Wu
9
9
  - Alexandre Terrasa
10
10
  - Peter Zhu
11
- autorequire:
11
+ autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2024-06-27 00:00:00.000000000 Z
14
+ date: 2024-08-06 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -61,7 +61,7 @@ dependencies:
61
61
  requirements:
62
62
  - - ">="
63
63
  - !ruby/object:Gem::Version
64
- version: 0.1.4
64
+ version: 0.1.14
65
65
  - - "<"
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0.2'
@@ -71,7 +71,7 @@ dependencies:
71
71
  requirements:
72
72
  - - ">="
73
73
  - !ruby/object:Gem::Version
74
- version: 0.1.4
74
+ version: 0.1.14
75
75
  - - "<"
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0.2'
@@ -131,7 +131,7 @@ dependencies:
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
- description:
134
+ description:
135
135
  email:
136
136
  - ruby@shopify.com
137
137
  executables:
@@ -186,6 +186,7 @@ files:
186
186
  - lib/tapioca/dsl/compilers/active_storage.rb
187
187
  - lib/tapioca/dsl/compilers/active_support_concern.rb
188
188
  - lib/tapioca/dsl/compilers/active_support_current_attributes.rb
189
+ - lib/tapioca/dsl/compilers/active_support_time_ext.rb
189
190
  - lib/tapioca/dsl/compilers/config.rb
190
191
  - lib/tapioca/dsl/compilers/frozen_record.rb
191
192
  - lib/tapioca/dsl/compilers/graphql_input_object.rb
@@ -274,7 +275,7 @@ licenses:
274
275
  - MIT
275
276
  metadata:
276
277
  allowed_push_host: https://rubygems.org
277
- post_install_message:
278
+ post_install_message:
278
279
  rdoc_options: []
279
280
  require_paths:
280
281
  - lib
@@ -289,8 +290,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
289
290
  - !ruby/object:Gem::Version
290
291
  version: '0'
291
292
  requirements: []
292
- rubygems_version: 3.5.13
293
- signing_key:
293
+ rubygems_version: 3.5.16
294
+ signing_key:
294
295
  specification_version: 4
295
296
  summary: A Ruby Interface file generator for gems, core types and the Ruby standard
296
297
  library