sorbet-rails 0.6.5.1 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -2
  3. data/.gitignore +2 -1
  4. data/.travis.yml +1 -1
  5. data/README.md +66 -13
  6. data/Rakefile +3 -3
  7. data/lib/bundled_rbi/customizabel_rbi_formatter.rbi +29 -0
  8. data/lib/bundled_rbi/pluck_to_tstruct.rbi +2 -1
  9. data/lib/bundled_rbi/typed_enum.rbi +7 -0
  10. data/lib/sorbet-rails.rb +1 -3
  11. data/lib/sorbet-rails/active_record_rbi_formatter.rb +6 -6
  12. data/lib/sorbet-rails/config.rb +12 -0
  13. data/lib/sorbet-rails/dependent_gem_rbis/activerecord.rbi +3 -0
  14. data/lib/sorbet-rails/dependent_gem_rbis/parlour.rbi +1896 -0
  15. data/lib/sorbet-rails/deprecation.rb +1 -0
  16. data/lib/sorbet-rails/gem_plugins/attr_json_plugin.rb +137 -0
  17. data/lib/sorbet-rails/gem_plugins/flag_shih_tzu_plugin.rb +201 -0
  18. data/lib/sorbet-rails/gem_plugins/kaminari_plugin.rb +28 -0
  19. data/lib/sorbet-rails/gem_plugins/shrine_plugin.rb +1 -1
  20. data/lib/sorbet-rails/helper_rbi_formatter.rb +1 -1
  21. data/lib/sorbet-rails/job_rbi_formatter.rb +75 -62
  22. data/lib/sorbet-rails/mailer_rbi_formatter.rb +40 -27
  23. data/lib/sorbet-rails/model_column_utils.rb +129 -0
  24. data/lib/sorbet-rails/model_plugins/active_record_assoc.rb +40 -1
  25. data/lib/sorbet-rails/model_plugins/active_record_attribute.rb +12 -112
  26. data/lib/sorbet-rails/model_plugins/active_record_serialized_attribute.rb +68 -0
  27. data/lib/sorbet-rails/model_plugins/base.rb +6 -8
  28. data/lib/sorbet-rails/model_plugins/plugins.rb +9 -0
  29. data/lib/sorbet-rails/model_rbi_formatter.rb +3 -3
  30. data/lib/sorbet-rails/model_utils.rb +5 -2
  31. data/lib/sorbet-rails/rails_mixins/generated_url_helpers.rb +2 -3
  32. data/lib/sorbet-rails/rails_mixins/pluck_to_tstruct.rb +54 -7
  33. data/lib/sorbet-rails/railtie.rb +0 -2
  34. data/lib/sorbet-rails/routes_rbi_formatter.rb +6 -2
  35. data/lib/sorbet-rails/sorbet_utils.rb +152 -150
  36. data/lib/sorbet-rails/tasks/rails_rbi.rake +9 -8
  37. data/sorbet-rails.gemspec +2 -2
  38. data/spec/bin/run_spec.sh +1 -1
  39. data/spec/generators/rails-template.rb +16 -0
  40. data/spec/generators/sorbet_test_cases.rb +28 -56
  41. data/spec/job_rbi_formatter_spec.rb +1 -1
  42. data/spec/pluck_to_tstruct_spec.rb +115 -16
  43. data/spec/rails_helper.rb +3 -7
  44. data/spec/rake_rails_rbi_jobs_spec.rb +20 -0
  45. data/spec/rake_rails_rbi_mailers_spec.rb +21 -0
  46. data/spec/sorbet_spec.rb +5 -5
  47. data/spec/support/v5.0/Gemfile +1 -1
  48. data/spec/support/v5.0/Gemfile.lock +23 -19
  49. data/spec/support/v5.0/app/controllers/application_controller.rb +1 -1
  50. data/spec/support/v5.0/app/models/headmaster.rb +1 -1
  51. data/spec/support/v5.0/app/models/potion.rb +1 -1
  52. data/spec/support/v5.0/app/models/robe.rb +1 -1
  53. data/spec/support/v5.0/app/models/school.rb +1 -1
  54. data/spec/support/v5.0/app/models/spell.rb +1 -1
  55. data/spec/support/v5.0/app/models/subject.rb +1 -1
  56. data/spec/support/v5.0/app/models/wizard.rb +5 -0
  57. data/spec/support/v5.0/config/environments/development.rb +1 -1
  58. data/spec/support/v5.0/config/environments/production.rb +1 -1
  59. data/spec/support/v5.0/config/environments/test.rb +1 -1
  60. data/spec/support/v5.0/config/routes.rb +1 -1
  61. data/spec/support/v5.0/db/migrate/20190620000015_add_serialized_to_wizards.rb +9 -0
  62. data/spec/support/v5.0/db/schema.rb +8 -4
  63. data/spec/support/v5.0/sorbet_test_cases.rb +28 -56
  64. data/spec/support/v5.1/Gemfile.lock +21 -17
  65. data/spec/support/v5.1/app/controllers/application_controller.rb +1 -1
  66. data/spec/support/v5.1/app/models/headmaster.rb +1 -1
  67. data/spec/support/v5.1/app/models/school.rb +1 -1
  68. data/spec/support/v5.1/app/models/wizard.rb +5 -0
  69. data/spec/support/v5.1/config/environments/production.rb +1 -1
  70. data/spec/support/v5.1/config/routes.rb +1 -1
  71. data/spec/support/v5.1/db/migrate/20190620000015_add_serialized_to_wizards.rb +9 -0
  72. data/spec/support/v5.1/db/schema.rb +5 -1
  73. data/spec/support/v5.1/sorbet_test_cases.rb +28 -56
  74. data/spec/support/v5.2/Gemfile +1 -1
  75. data/spec/support/v5.2/Gemfile.lock +23 -19
  76. data/spec/support/v5.2/app/models/headmaster.rb +1 -1
  77. data/spec/support/v5.2/app/models/school.rb +1 -1
  78. data/spec/support/v5.2/app/models/wizard.rb +5 -0
  79. data/spec/support/v5.2/config/environments/development.rb +1 -1
  80. data/spec/support/v5.2/config/environments/production.rb +1 -1
  81. data/spec/support/v5.2/config/environments/test.rb +1 -1
  82. data/spec/support/v5.2/config/routes.rb +1 -1
  83. data/spec/support/v5.2/db/migrate/20190620000015_add_serialized_to_wizards.rb +9 -0
  84. data/spec/support/v5.2/db/schema.rb +5 -1
  85. data/spec/support/v5.2/sorbet_test_cases.rb +28 -56
  86. data/spec/support/v6.0/.gitignore +6 -0
  87. data/spec/support/v6.0/Gemfile +3 -3
  88. data/spec/support/v6.0/Gemfile.lock +89 -84
  89. data/spec/support/v6.0/app/models/wizard.rb +5 -0
  90. data/spec/support/v6.0/bin/bundle +22 -13
  91. data/spec/support/v6.0/config/environments/development.rb +1 -1
  92. data/spec/support/v6.0/config/environments/production.rb +1 -1
  93. data/spec/support/v6.0/config/environments/test.rb +2 -2
  94. data/spec/support/v6.0/config/routes.rb +1 -1
  95. data/spec/support/v6.0/db/migrate/20190620000015_add_serialized_to_wizards.rb +9 -0
  96. data/spec/support/v6.0/db/schema.rb +5 -1
  97. data/spec/support/v6.0/sorbet_test_cases.rb +28 -56
  98. data/spec/support/v6.0/tmp/pids/.keep +0 -0
  99. data/spec/test_data/v5.0/expected_active_record_relation.rbi +0 -1
  100. data/spec/test_data/v5.0/expected_application_job.rbi +2 -2
  101. data/spec/test_data/v5.0/expected_award_house_point_hourglasses.rbi +2 -2
  102. data/spec/test_data/v5.0/expected_custom_application_job.rbi +21 -0
  103. data/spec/test_data/v5.0/expected_custom_application_mailer.rbi +6 -0
  104. data/spec/test_data/v5.0/expected_custom_award_house_point_hourglasses.rbi +21 -0
  105. data/spec/test_data/v5.0/expected_custom_daily_prophet_mailer.rbi +8 -0
  106. data/spec/test_data/v5.0/expected_custom_hogwarts_acceptance_mailer.rbi +21 -0
  107. data/spec/test_data/v5.0/expected_headmaster.rbi +24 -0
  108. data/spec/test_data/v5.0/expected_potion.rbi +12 -0
  109. data/spec/test_data/v5.0/expected_robe.rbi +12 -0
  110. data/spec/test_data/v5.0/expected_routes.rbi +4 -0
  111. data/spec/test_data/v5.0/expected_school.rbi +12 -0
  112. data/spec/test_data/v5.0/expected_spell/habtm_spell_books.rbi +24 -0
  113. data/spec/test_data/v5.0/expected_spell_book.rbi +21 -9
  114. data/spec/test_data/v5.0/expected_spell_book/habtm_spells.rbi +24 -0
  115. data/spec/test_data/v5.0/expected_squib.rbi +63 -0
  116. data/spec/test_data/v5.0/expected_subject/habtm_wizards.rbi +24 -0
  117. data/spec/test_data/v5.0/expected_wand.rbi +22 -10
  118. data/spec/test_data/v5.0/expected_wizard.rbi +121 -58
  119. data/spec/test_data/v5.0/expected_wizard/habtm_subjects.rbi +24 -0
  120. data/spec/test_data/v5.0/expected_wizard_wo_spellbook.rbi +121 -58
  121. data/spec/test_data/v5.1/expected_active_record_relation.rbi +0 -1
  122. data/spec/test_data/v5.1/expected_application_job.rbi +2 -2
  123. data/spec/test_data/v5.1/expected_award_house_point_hourglasses.rbi +2 -2
  124. data/spec/test_data/v5.1/expected_custom_application_job.rbi +21 -0
  125. data/spec/test_data/v5.1/expected_custom_application_mailer.rbi +6 -0
  126. data/spec/test_data/v5.1/expected_custom_award_house_point_hourglasses.rbi +21 -0
  127. data/spec/test_data/v5.1/expected_custom_daily_prophet_mailer.rbi +8 -0
  128. data/spec/test_data/v5.1/expected_custom_hogwarts_acceptance_mailer.rbi +21 -0
  129. data/spec/test_data/v5.1/expected_headmaster.rbi +24 -0
  130. data/spec/test_data/v5.1/expected_potion.rbi +12 -0
  131. data/spec/test_data/v5.1/expected_robe.rbi +12 -0
  132. data/spec/test_data/v5.1/expected_routes.rbi +4 -0
  133. data/spec/test_data/v5.1/expected_school.rbi +12 -0
  134. data/spec/test_data/v5.1/expected_spell/habtm_spell_books.rbi +24 -0
  135. data/spec/test_data/v5.1/expected_spell_book.rbi +21 -9
  136. data/spec/test_data/v5.1/expected_spell_book/habtm_spells.rbi +24 -0
  137. data/spec/test_data/v5.1/expected_squib.rbi +63 -0
  138. data/spec/test_data/v5.1/expected_subject/habtm_wizards.rbi +24 -0
  139. data/spec/test_data/v5.1/expected_wand.rbi +22 -10
  140. data/spec/test_data/v5.1/expected_wizard.rbi +121 -58
  141. data/spec/test_data/v5.1/expected_wizard/habtm_subjects.rbi +24 -0
  142. data/spec/test_data/v5.1/expected_wizard_wo_spellbook.rbi +121 -58
  143. data/spec/test_data/v5.2/expected_active_record_relation.rbi +0 -1
  144. data/spec/test_data/v5.2/expected_application_job.rbi +2 -2
  145. data/spec/test_data/v5.2/expected_attachment.rbi +24 -0
  146. data/spec/test_data/v5.2/expected_award_house_point_hourglasses.rbi +2 -2
  147. data/spec/test_data/v5.2/expected_blob.rbi +25 -1
  148. data/spec/test_data/v5.2/expected_custom_application_job.rbi +21 -0
  149. data/spec/test_data/v5.2/expected_custom_application_mailer.rbi +6 -0
  150. data/spec/test_data/v5.2/expected_custom_award_house_point_hourglasses.rbi +21 -0
  151. data/spec/test_data/v5.2/expected_custom_daily_prophet_mailer.rbi +8 -0
  152. data/spec/test_data/v5.2/expected_custom_hogwarts_acceptance_mailer.rbi +21 -0
  153. data/spec/test_data/v5.2/expected_headmaster.rbi +24 -0
  154. data/spec/test_data/v5.2/expected_potion.rbi +12 -0
  155. data/spec/test_data/v5.2/expected_robe.rbi +12 -0
  156. data/spec/test_data/v5.2/expected_routes.rbi +4 -0
  157. data/spec/test_data/v5.2/expected_school.rbi +12 -0
  158. data/spec/test_data/v5.2/expected_spell/habtm_spell_books.rbi +24 -0
  159. data/spec/test_data/v5.2/expected_spell_book.rbi +21 -9
  160. data/spec/test_data/v5.2/expected_spell_book/habtm_spells.rbi +24 -0
  161. data/spec/test_data/v5.2/expected_squib.rbi +89 -2
  162. data/spec/test_data/v5.2/expected_subject/habtm_wizards.rbi +24 -0
  163. data/spec/test_data/v5.2/expected_wand.rbi +22 -10
  164. data/spec/test_data/v5.2/expected_wizard.rbi +147 -60
  165. data/spec/test_data/v5.2/expected_wizard/habtm_subjects.rbi +24 -0
  166. data/spec/test_data/v5.2/expected_wizard_wo_spellbook.rbi +147 -60
  167. data/spec/test_data/v6.0/expected_active_record_relation.rbi +0 -1
  168. data/spec/test_data/v6.0/expected_application_job.rbi +2 -2
  169. data/spec/test_data/v6.0/expected_attachment.rbi +24 -0
  170. data/spec/test_data/v6.0/expected_award_house_point_hourglasses.rbi +2 -2
  171. data/spec/test_data/v6.0/expected_blob.rbi +25 -1
  172. data/spec/test_data/v6.0/expected_custom_application_job.rbi +21 -0
  173. data/spec/test_data/v6.0/expected_custom_application_mailer.rbi +6 -0
  174. data/spec/test_data/v6.0/expected_custom_award_house_point_hourglasses.rbi +21 -0
  175. data/spec/test_data/v6.0/expected_custom_daily_prophet_mailer.rbi +8 -0
  176. data/spec/test_data/v6.0/expected_custom_hogwarts_acceptance_mailer.rbi +21 -0
  177. data/spec/test_data/v6.0/expected_headmaster.rbi +24 -0
  178. data/spec/test_data/v6.0/expected_potion.rbi +12 -0
  179. data/spec/test_data/v6.0/expected_robe.rbi +12 -0
  180. data/spec/test_data/v6.0/expected_routes.rbi +4 -0
  181. data/spec/test_data/v6.0/expected_school.rbi +12 -0
  182. data/spec/test_data/v6.0/expected_spell/habtm_spell_books.rbi +24 -0
  183. data/spec/test_data/v6.0/expected_spell_book.rbi +21 -9
  184. data/spec/test_data/v6.0/expected_spell_book/habtm_spells.rbi +24 -0
  185. data/spec/test_data/v6.0/expected_squib.rbi +89 -2
  186. data/spec/test_data/v6.0/expected_subject/habtm_wizards.rbi +24 -0
  187. data/spec/test_data/v6.0/expected_wand.rbi +22 -10
  188. data/spec/test_data/v6.0/expected_wizard.rbi +147 -60
  189. data/spec/test_data/v6.0/expected_wizard/habtm_subjects.rbi +24 -0
  190. data/spec/test_data/v6.0/expected_wizard_wo_spellbook.rbi +147 -60
  191. data/spec/tstruct_comparable.rb +13 -0
  192. metadata +64 -15
  193. data/lib/bundled_rbi/parameters.rbi +0 -28
  194. data/lib/sorbet-rails/custom_types/boolean_string.rb +0 -42
  195. data/lib/sorbet-rails/custom_types/integer_string.rb +0 -45
  196. data/lib/sorbet-rails/rails_mixins/custom_params_methods.rb +0 -57
  197. data/spec/boolean_string_spec.rb +0 -59
  198. data/spec/custom_params_methods_spec.rb +0 -138
  199. data/spec/integer_string_spec.rb +0 -46
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  require 'active_support/deprecation'
2
3
 
3
4
  module SorbetRails
@@ -0,0 +1,137 @@
1
+ # typed: false
2
+ class AttrJsonPlugin < SorbetRails::ModelPlugins::Base
3
+ sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
4
+ def generate(root)
5
+ return unless @model_class.include?(::AttrJson::Record)
6
+
7
+ # Module for instance methods
8
+ obj_custom_module_name = self.model_module_name("GeneratedAttrJsonMethods")
9
+ obj_custom_module_rbi = root.create_module(obj_custom_module_name)
10
+
11
+ # Module for class methods
12
+ klass_custom_module_name = self.model_module_name("GeneratedAttrJsonClassMethods")
13
+ klass_custom_module_rbi = root.create_module(klass_custom_module_name)
14
+
15
+ # here we re-create the model class!
16
+ model_class_rbi = root.create_class(self.model_class_name)
17
+ model_class_rbi.create_include(obj_custom_module_name)
18
+ model_class_rbi.create_extend(klass_custom_module_name)
19
+
20
+ # then create custom methods, constants, etc. for this module.
21
+ add_class_methods(klass_custom_module_rbi)
22
+
23
+ @model_class.attr_json_registry.definitions.each do |definition|
24
+ add_methods_for_attributes(definition, obj_custom_module_rbi)
25
+ end
26
+
27
+ if @model_class.include?(::AttrJson::Record::Dirty)
28
+ obj_custom_module_rbi.create_method(
29
+ 'attr_json_changes',
30
+ returns: 'AttrJson::Record::Dirty::Implementation'
31
+ )
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ sig { params(custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
38
+ def add_class_methods(custom_module_rbi)
39
+ custom_module_rbi.create_method(
40
+ 'attr_json_config',
41
+ parameters: [
42
+ ::Parlour::RbiGenerator::Parameter.new(
43
+ 'new_values',
44
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
45
+ )
46
+ ],
47
+ returns: 'T::Hash[Symbol, T.untyped]'
48
+ )
49
+
50
+ custom_module_rbi.create_method(
51
+ 'attr_json',
52
+ parameters: [
53
+ ::Parlour::RbiGenerator::Parameter.new(
54
+ 'name',
55
+ type: 'T.any(Symbol, String)'
56
+ ),
57
+ ::Parlour::RbiGenerator::Parameter.new(
58
+ 'type',
59
+ type: 'T.any(Symbol, ActiveModel::Type::Value)'
60
+ ),
61
+ ::Parlour::RbiGenerator::Parameter.new(
62
+ '**options',
63
+ type: 'T.untyped'
64
+ )
65
+ ]
66
+ )
67
+ end
68
+
69
+ sig do
70
+ params(
71
+ definition: ::AttrJson::AttributeDefinition,
72
+ custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace
73
+ )
74
+ .void
75
+ end
76
+ def add_methods_for_attributes(definition, custom_module_rbi)
77
+ # set methods can receive an argument of any type because attr_json will try
78
+ # to parse to the correct type. Example:
79
+ #
80
+ # class Post < ApplicationRecord
81
+ # ...
82
+ # attr_json :my_datetime, :datetime
83
+ # end
84
+ #
85
+ # > p = Post.new
86
+ # > (p.my_datetime = '2020-02-02').class
87
+ # => String
88
+ # > p.my_datetime.class
89
+ # => Time
90
+ #
91
+ # Also, the setter type return is the same as its argument type (before parse).
92
+ custom_module_rbi.create_method(
93
+ "#{definition.name}=",
94
+ parameters: [
95
+ ::Parlour::RbiGenerator::Parameter.new(
96
+ 'value',
97
+ type: 'T.untyped'
98
+ )
99
+ ],
100
+ returns: 'T.untyped'
101
+ )
102
+
103
+ definition_type = get_definition_type(definition)
104
+
105
+ custom_module_rbi.create_method(
106
+ definition.name.to_s,
107
+ returns: definition_type
108
+ )
109
+
110
+ custom_module_rbi.create_method(
111
+ "#{definition.name}?",
112
+ returns: 'T::Boolean'
113
+ )
114
+ end
115
+
116
+ sig { params(definition: ::AttrJson::AttributeDefinition).returns(String) }
117
+ def get_definition_type(definition)
118
+
119
+ if definition.array_type?
120
+ "T::Array[#{type_to_class(definition.type.base_type.type.to_s)}]"
121
+ else
122
+ "T.nilable(#{type_to_class(definition.type.type.to_s)})"
123
+ end
124
+ end
125
+
126
+ sig { params(type: String).returns(String) }
127
+ def type_to_class(type)
128
+ return 'T.untyped' unless type.present?
129
+
130
+ case type
131
+ when 'datetime' then 'Time'
132
+ when 'decimal' then 'BigDecimal'
133
+ when 'boolean' then 'T::Boolean'
134
+ else type.camelize
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,201 @@
1
+ # typed: false
2
+ class FlagShihTzuPlugin < SorbetRails::ModelPlugins::Base
3
+ sig { override.params(root: Parlour::RbiGenerator::Namespace).void }
4
+ def generate(root)
5
+ return unless @model_class.include?(::FlagShihTzu)
6
+
7
+ obj_custom_module_name = self.model_module_name("GeneratedFlagShihTzuMethods")
8
+ obj_custom_module_rbi = root.create_module(obj_custom_module_name)
9
+
10
+ klass_custom_module_name = self.model_module_name("GeneratedFlagShihTzuClassMethods")
11
+ klass_custom_module_rbi = root.create_module(klass_custom_module_name)
12
+
13
+
14
+ # here we re-create the model class!
15
+ model_class_rbi = root.create_class(self.model_class_name)
16
+ model_class_rbi.create_include(obj_custom_module_name)
17
+ model_class_rbi.create_extend(klass_custom_module_name)
18
+
19
+ # then create custom methods, constants, etc. for this module.
20
+ add_class_methods(klass_custom_module_rbi)
21
+
22
+ if @model_class.flag_columns.present?
23
+ @model_class
24
+ .flag_columns
25
+ .each do |column|
26
+ add_methods_for_column(column, obj_custom_module_rbi)
27
+ end
28
+ end
29
+
30
+ if @model_class.flag_mapping.present?
31
+ @model_class
32
+ .flag_mapping
33
+ .each do |column, flags|
34
+ flags.keys
35
+ .select { |flag_key| really_has_the_flag?(flag_key) }
36
+ .each do |flag_key|
37
+ add_methods_for_flag(column, flag_key, obj_custom_module_rbi)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ sig { params(custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
46
+ def add_class_methods(custom_module_rbi)
47
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L12
48
+ custom_module_rbi.create_method(
49
+ 'flag_options',
50
+ returns: 'T::Hash[String, T::Hash[Symbol, T.untyped]]'
51
+ )
52
+
53
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L13
54
+ custom_module_rbi.create_method(
55
+ 'flag_mapping',
56
+ returns: 'T::Hash[String, T::Hash[Symbol, Integer]]'
57
+ )
58
+
59
+ # https://github.com/pboling/flag_shih_tzu/blob/6a3f1c5f62bd56aa932252eef935826c9674b096/lib/flag_shih_tzu.rb#L14
60
+ custom_module_rbi.create_method(
61
+ 'flag_columns',
62
+ returns: 'T::Array[Symbol]'
63
+ )
64
+
65
+ # https://github.com/pboling/flag_shih_tzu#updating-flag-column-by-raw-sql
66
+ custom_module_rbi.create_method(
67
+ 'set_flag_sql',
68
+ parameters: [
69
+ ::Parlour::RbiGenerator::Parameter.new(
70
+ 'flag',
71
+ type: 'Symbol'
72
+ ),
73
+ ::Parlour::RbiGenerator::Parameter.new(
74
+ 'value',
75
+ type: 'T::Boolean'
76
+ ),
77
+ ::Parlour::RbiGenerator::Parameter.new(
78
+ 'colmn',
79
+ type: 'T.nilable(String)'
80
+ ),
81
+ ::Parlour::RbiGenerator::Parameter.new(
82
+ 'custom_table_name',
83
+ type: 'T.any(String, Symbol)'
84
+ )
85
+ ],
86
+ returns: 'T::Hash[String, T::Hash[Symbol, T.untyped]]'
87
+ )
88
+
89
+ if @model_class.flag_mapping.present?
90
+ # https://github.com/pboling/flag_shih_tzu#support-for-manually-building-conditions
91
+ @model_class
92
+ .flag_mapping
93
+ .flat_map { |_, flags| flags.keys }
94
+ .each do |flag_key|
95
+ next unless really_has_the_flag?(flag_key)
96
+
97
+ custom_module_rbi.create_method(
98
+ "#{flag_key}_condition",
99
+ parameters: [
100
+ ::Parlour::RbiGenerator::Parameter.new(
101
+ 'options',
102
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
103
+ )
104
+ ],
105
+ returns: 'String'
106
+ )
107
+
108
+ custom_module_rbi.create_method(
109
+ "not_#{flag_key}_condition",
110
+ parameters: [
111
+ ::Parlour::RbiGenerator::Parameter.new(
112
+ 'options',
113
+ type: 'T.nilable(T::Hash[Symbol, T.untyped])'
114
+ )
115
+ ],
116
+ returns: 'String'
117
+ )
118
+ end
119
+ end
120
+ end
121
+
122
+ # https://github.com/pboling/flag_shih_tzu#generated-boolean-patterned-instance-methods
123
+ sig { params(column: String, custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
124
+ def add_methods_for_column(column, custom_module_rbi)
125
+ custom_module_rbi.create_method(
126
+ "all_#{column}",
127
+ returns: 'T::Array[Symbol]'
128
+ )
129
+
130
+ custom_module_rbi.create_method(
131
+ "selected_#{column}",
132
+ returns: 'T::Array[Symbol]'
133
+ )
134
+
135
+ custom_module_rbi.create_method(
136
+ "select_all_#{column}",
137
+ returns: 'T::Array[Symbol]'
138
+ )
139
+
140
+ custom_module_rbi.create_method(
141
+ "unselect_all_#{column}",
142
+ returns: 'T::Array[Symbol]'
143
+ )
144
+
145
+ custom_module_rbi.create_method(
146
+ "selected_#{column}=",
147
+ parameters: [
148
+ ::Parlour::RbiGenerator::Parameter.new(
149
+ 'chosen_flags',
150
+ type: 'T.nilable(T::Array[Symbol])'
151
+ )
152
+ ],
153
+ returns: 'T::Array[Symbol]'
154
+ )
155
+
156
+ end
157
+
158
+ # https://github.com/pboling/flag_shih_tzu#generated-boolean-patterned-instance-methods
159
+ sig { params(column: String, flag_key: Symbol, custom_module_rbi: Parlour::RbiGenerator::ModuleNamespace).void }
160
+ def add_methods_for_flag(column, flag_key, custom_module_rbi)
161
+ custom_module_rbi.create_method(flag_key.to_s, returns: 'T::Boolean')
162
+ custom_module_rbi.create_method("#{flag_key}?", returns: 'T::Boolean')
163
+ custom_module_rbi.create_method(
164
+ "#{flag_key}=",
165
+ parameters: [
166
+ ::Parlour::RbiGenerator::Parameter.new(
167
+ 'value',
168
+ type: 'T::Boolean'
169
+ )
170
+ ],
171
+ returns: 'T::Boolean'
172
+ )
173
+
174
+ custom_module_rbi.create_method("not_#{flag_key}", returns: 'T::Boolean')
175
+ custom_module_rbi.create_method("not_#{flag_key}?", returns: 'T::Boolean')
176
+ custom_module_rbi.create_method(
177
+ "not_#{flag_key}=",
178
+ parameters: [
179
+ ::Parlour::RbiGenerator::Parameter.new(
180
+ 'value',
181
+ type: 'T::Boolean'
182
+ )
183
+ ],
184
+ returns: 'T::Boolean'
185
+ )
186
+
187
+ custom_module_rbi.create_method("#{flag_key}_changed?", returns: 'T::Boolean')
188
+
189
+ custom_module_rbi.create_method("has_#{flag_key}?", returns: 'T::Boolean')
190
+
191
+ if @model_class.flag_options[column][:bang_methods]
192
+ custom_module_rbi.create_method("#{flag_key}!", returns: 'T::Boolean')
193
+ custom_module_rbi.create_method("not_#{flag_key}!", returns: 'T::Boolean')
194
+ end
195
+ end
196
+
197
+ sig { params(flag_name: Symbol).returns(T::Boolean) }
198
+ def really_has_the_flag?(flag_name)
199
+ @model_class.respond_to?("#{flag_name}_condition")
200
+ end
201
+ end
@@ -35,5 +35,33 @@ class KaminariPlugin < SorbetRails::ModelPlugins::Base
35
35
  Parameter.new('num', type: 'Integer')
36
36
  ],
37
37
  )
38
+
39
+ # https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-core/lib/kaminari/models/configuration_methods.rb#L19
40
+ model_class_rbi = root.create_class(model_class_name)
41
+ model_class_rbi.create_method(
42
+ "default_per_page",
43
+ return_type: "Integer",
44
+ class_method: true,
45
+ )
46
+
47
+ # https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-core/lib/kaminari/models/page_scope_methods.rb#L82
48
+ model_relation_rbi = root.create_class(self.model_relation_class_name)
49
+ model_relation_rbi.create_method(
50
+ 'last_page?',
51
+ parameters: nil,
52
+ return_type: 'T::Boolean',
53
+ )
54
+ model_assoc_relation_rbi = root.create_class(self.model_assoc_relation_class_name)
55
+ model_assoc_relation_rbi.create_method(
56
+ 'last_page?',
57
+ parameters: nil,
58
+ return_type: 'T::Boolean',
59
+ )
60
+ collection_proxy_rbi = root.create_class(self.model_assoc_proxy_class_name)
61
+ collection_proxy_rbi.create_method(
62
+ 'last_page?',
63
+ parameters: nil,
64
+ return_type: 'T::Boolean',
65
+ )
38
66
  end
39
67
  end
@@ -45,7 +45,7 @@ class ShrinePlugin < SorbetRails::ModelPlugins::Base
45
45
  parameters: [
46
46
  ::Parlour::RbiGenerator::Parameter.new(
47
47
  "url",
48
- type: T.untyped # TODO likely T.nilable(String)
48
+ type: "T.untyped" # TODO likely T.nilable(String)
49
49
  ),
50
50
  ],
51
51
  )
@@ -16,7 +16,7 @@ class SorbetRails::HelperRbiFormatter
16
16
  def generate_rbi
17
17
  puts "-- Generate sigs for helpers --"
18
18
 
19
- @parlour.root.add_comments([
19
+ @parlour.root.add_comment([
20
20
  'This is an autogenerated file for Rails helpers.',
21
21
  'Please rerun bundle exec rake rails_rbi:helpers to regenerate.'
22
22
  ])
@@ -2,74 +2,87 @@
2
2
  require('parlour')
3
3
  require('sorbet-rails/sorbet_utils.rb')
4
4
 
5
- class SorbetRails::JobRbiFormatter
6
- extend T::Sig
5
+ module SorbetRails
6
+ class JobRbiFormatter
7
+ extend T::Sig
7
8
 
8
- Parameter = ::Parlour::RbiGenerator::Parameter
9
+ Parameter = ::Parlour::RbiGenerator::Parameter
9
10
 
10
- sig { params(job_class: T.class_of(ActiveJob::Base)).void }
11
- def initialize(job_class)
12
- @job_class = T.let(job_class, T.class_of(ActiveJob::Base))
13
- @parlour = T.let(Parlour::RbiGenerator.new, Parlour::RbiGenerator)
14
- end
11
+ sig { returns(Parlour::RbiGenerator) }
12
+ attr_reader :rbi_generator
13
+
14
+ sig { returns(T.class_of(ActiveJob::Base)) }
15
+ attr_reader :job_class
15
16
 
16
- sig {returns(String)}
17
- def generate_rbi
18
- puts "-- Generate sigs for mailer #{@job_class.name} --"
17
+ sig { params(job_class: T.class_of(ActiveJob::Base)).void }
18
+ def initialize(job_class)
19
+ @job_class = T.let(job_class, T.class_of(ActiveJob::Base))
20
+ @rbi_generator = T.let(Parlour::RbiGenerator.new, Parlour::RbiGenerator)
21
+ end
19
22
 
20
- @parlour.root.add_comments([
21
- 'This is an autogenerated file for Rails\' jobs.',
22
- 'Please rerun bundle exec rake rails_rbi:jobs to regenerate.'
23
- ])
23
+ sig { void }
24
+ def populate_rbi
25
+ @rbi_generator.root.add_comment([
26
+ 'This is an autogenerated file for Rails\' jobs.',
27
+ 'Please rerun bundle exec rake rails_rbi:jobs to regenerate.'
28
+ ])
24
29
 
25
- @parlour.root.create_class(@job_class.name) do |job_rbi|
26
- method_def = @job_class.instance_method(:perform)
27
- parameters = SorbetRails::SorbetUtils.parameters_from_method_def(method_def)
28
- job_rbi.create_method(
29
- "perform_later",
30
- parameters: parameters,
31
- class_method: true,
32
- )
33
- job_rbi.create_method(
34
- "perform_now",
35
- parameters: parameters,
36
- class_method: true,
37
- )
38
- # Override the signature for "set" so that we can support it
39
- # At run-time, this method returns a `ActiveJob::ConfiguredJob` but
40
- # we fake the signature to return "T.self_class" so that
41
- # sorbet can type-check when `perform_later` is called on it
42
- # See: https://guides.rubyonrails.org/active_job_basics.html#enqueue-the-job
43
- job_rbi.create_method(
44
- "set",
45
- # Documentation: https://api.rubyonrails.org/classes/ActiveJob/Core/ClassMethods.html
46
- parameters: [
47
- Parameter.new(
48
- "wait:",
49
- type: "T.nilable(ActiveSupport::Duration)",
50
- default: "nil",
51
- ),
52
- Parameter.new(
53
- "wait_until:",
54
- type: "T.nilable(T.any(ActiveSupport::TimeWithZone, Date, Time))",
55
- default: "nil",
56
- ),
57
- Parameter.new(
58
- "queue:",
59
- type: "T.nilable(T.any(String, Symbol))",
60
- default: "nil",
61
- ),
62
- Parameter.new(
63
- "priority:",
64
- type: "T.nilable(Integer)",
65
- default: "nil",
66
- ),
67
- ],
68
- return_type: "T.self_type",
69
- class_method: true,
70
- )
30
+ @rbi_generator.root.create_class(T.must(@job_class.name)) do |job_rbi|
31
+ method_def = @job_class.instance_method(:perform)
32
+ parameters = SorbetRails::SorbetUtils.parameters_from_method_def(method_def)
33
+ job_rbi.create_method(
34
+ "perform_later",
35
+ parameters: parameters,
36
+ class_method: true,
37
+ return_type: @job_class.name,
38
+ )
39
+ job_rbi.create_method(
40
+ "perform_now",
41
+ parameters: parameters,
42
+ class_method: true,
43
+ return_type: @job_class.name,
44
+ )
45
+ # Override the signature for "set" so that we can support it
46
+ # At run-time, this method returns a `ActiveJob::ConfiguredJob` but
47
+ # we fake the signature to return "T.self_class" so that
48
+ # sorbet can type-check when `perform_later` is called on it
49
+ # See: https://guides.rubyonrails.org/active_job_basics.html#enqueue-the-job
50
+ job_rbi.create_method(
51
+ "set",
52
+ # Documentation: https://api.rubyonrails.org/classes/ActiveJob/Core/ClassMethods.html
53
+ parameters: [
54
+ Parameter.new(
55
+ "wait:",
56
+ type: "T.nilable(ActiveSupport::Duration)",
57
+ default: "nil",
58
+ ),
59
+ Parameter.new(
60
+ "wait_until:",
61
+ type: "T.nilable(T.any(ActiveSupport::TimeWithZone, Date, Time))",
62
+ default: "nil",
63
+ ),
64
+ Parameter.new(
65
+ "queue:",
66
+ type: "T.nilable(T.any(String, Symbol))",
67
+ default: "nil",
68
+ ),
69
+ Parameter.new(
70
+ "priority:",
71
+ type: "T.nilable(Integer)",
72
+ default: "nil",
73
+ ),
74
+ ],
75
+ return_type: "T.self_type",
76
+ class_method: true,
77
+ )
78
+ end
71
79
  end
72
80
 
73
- @parlour.rbi
81
+ sig { returns(String) }
82
+ def generate_rbi
83
+ puts "-- Generate sigs for mailer #{@job_class.name} --"
84
+ populate_rbi
85
+ @rbi_generator.rbi
86
+ end
74
87
  end
75
88
  end