tapioca 0.16.10 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ruby_lsp/tapioca/addon.rb +24 -20
- data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +20 -20
- data/lib/tapioca/bundler_ext/auto_require_hook.rb +5 -10
- data/lib/tapioca/commands/abstract_dsl.rb +36 -62
- data/lib/tapioca/commands/abstract_gem.rb +23 -43
- data/lib/tapioca/commands/annotations.rb +27 -33
- data/lib/tapioca/commands/check_shims.rb +4 -13
- data/lib/tapioca/commands/command.rb +8 -20
- data/lib/tapioca/commands/command_without_tracker.rb +1 -1
- data/lib/tapioca/commands/configure.rb +11 -16
- data/lib/tapioca/commands/dsl_compiler_list.rb +2 -1
- data/lib/tapioca/commands/dsl_generate.rb +2 -1
- data/lib/tapioca/commands/dsl_verify.rb +2 -1
- data/lib/tapioca/commands/gem_generate.rb +4 -8
- data/lib/tapioca/commands/gem_sync.rb +2 -1
- data/lib/tapioca/commands/gem_verify.rb +3 -2
- data/lib/tapioca/commands/require.rb +3 -7
- data/lib/tapioca/commands/todo.rb +6 -10
- data/lib/tapioca/dsl/compiler.rb +28 -53
- data/lib/tapioca/dsl/compilers/aasm.rb +31 -41
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +7 -5
- data/lib/tapioca/dsl/compilers/action_mailer.rb +5 -3
- data/lib/tapioca/dsl/compilers/action_text.rb +5 -3
- data/lib/tapioca/dsl/compilers/active_job.rb +5 -8
- data/lib/tapioca/dsl/compilers/active_model_attributes.rb +9 -7
- data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +4 -2
- data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +4 -2
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +16 -42
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +19 -24
- data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +7 -5
- data/lib/tapioca/dsl/compilers/active_record_enum.rb +6 -4
- data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +53 -61
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +86 -119
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +7 -11
- data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +4 -2
- data/lib/tapioca/dsl/compilers/active_record_store.rb +4 -2
- data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +18 -26
- data/lib/tapioca/dsl/compilers/active_resource.rb +18 -19
- data/lib/tapioca/dsl/compilers/active_storage.rb +5 -5
- data/lib/tapioca/dsl/compilers/active_support_concern.rb +8 -6
- data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +7 -5
- data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +4 -2
- data/lib/tapioca/dsl/compilers/config.rb +4 -2
- data/lib/tapioca/dsl/compilers/frozen_record.rb +6 -9
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +8 -8
- data/lib/tapioca/dsl/compilers/graphql_mutation.rb +5 -8
- data/lib/tapioca/dsl/compilers/identity_cache.rb +10 -37
- data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +8 -16
- data/lib/tapioca/dsl/compilers/kredis.rb +6 -4
- data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +4 -2
- data/lib/tapioca/dsl/compilers/protobuf.rb +12 -24
- data/lib/tapioca/dsl/compilers/rails_generators.rb +8 -9
- data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +22 -11
- data/lib/tapioca/dsl/compilers/smart_properties.rb +11 -20
- data/lib/tapioca/dsl/compilers/state_machines.rb +14 -24
- data/lib/tapioca/dsl/compilers/url_helpers.rb +9 -7
- data/lib/tapioca/dsl/compilers.rb +4 -7
- data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +13 -16
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +13 -28
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +19 -15
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +5 -24
- data/lib/tapioca/dsl/pipeline.rb +30 -58
- data/lib/tapioca/executor.rb +6 -12
- data/lib/tapioca/gem/events.rb +22 -28
- data/lib/tapioca/gem/listeners/base.rb +6 -6
- data/lib/tapioca/gem/listeners/dynamic_mixins.rb +4 -2
- data/lib/tapioca/gem/listeners/foreign_constants.rb +5 -7
- data/lib/tapioca/gem/listeners/methods.rb +15 -34
- data/lib/tapioca/gem/listeners/mixins.rb +6 -18
- data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_helpers.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_props.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +4 -2
- data/lib/tapioca/gem/listeners/sorbet_signatures.rb +7 -5
- data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +6 -4
- data/lib/tapioca/gem/listeners/source_location.rb +7 -4
- data/lib/tapioca/gem/listeners/subconstants.rb +5 -4
- data/lib/tapioca/gem/listeners/yard_doc.rb +23 -22
- data/lib/tapioca/gem/pipeline.rb +57 -72
- data/lib/tapioca/gem_info.rb +1 -1
- data/lib/tapioca/gemfile.rb +64 -73
- data/lib/tapioca/helpers/cli_helper.rb +3 -3
- data/lib/tapioca/helpers/config_helper.rb +15 -24
- data/lib/tapioca/helpers/env_helper.rb +1 -1
- data/lib/tapioca/helpers/gem_helper.rb +5 -5
- data/lib/tapioca/helpers/git_attributes.rb +3 -3
- data/lib/tapioca/helpers/rbi_files_helper.rb +73 -67
- data/lib/tapioca/helpers/rbi_helper.rb +14 -22
- data/lib/tapioca/helpers/sorbet_helper.rb +9 -18
- data/lib/tapioca/helpers/source_uri.rb +15 -25
- data/lib/tapioca/helpers/test/content.rb +6 -6
- data/lib/tapioca/helpers/test/dsl_compiler.rb +19 -29
- data/lib/tapioca/helpers/test/isolation.rb +4 -4
- data/lib/tapioca/helpers/test/template.rb +5 -7
- data/lib/tapioca/internal.rb +5 -1
- data/lib/tapioca/loaders/dsl.rb +11 -19
- data/lib/tapioca/loaders/gem.rb +6 -21
- data/lib/tapioca/loaders/loader.rb +15 -27
- data/lib/tapioca/rbi_ext/model.rb +12 -37
- data/lib/tapioca/rbi_formatter.rb +10 -19
- data/lib/tapioca/rbs/rewriter.rb +55 -0
- data/lib/tapioca/repo_index.rb +7 -7
- data/lib/tapioca/runtime/attached_class_of_32.rb +1 -1
- data/lib/tapioca/runtime/attached_class_of_legacy.rb +1 -1
- data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +23 -23
- data/lib/tapioca/runtime/generic_type_registry.rb +13 -23
- data/lib/tapioca/runtime/reflection.rb +48 -56
- data/lib/tapioca/runtime/trackers/autoload.rb +4 -8
- data/lib/tapioca/runtime/trackers/mixin.rb +6 -10
- data/lib/tapioca/runtime/trackers/required_ancestor.rb +3 -3
- data/lib/tapioca/runtime/trackers/tracker.rb +2 -2
- data/lib/tapioca/runtime/trackers.rb +4 -8
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +9 -15
- data/lib/tapioca/sorbet_ext/name_patch.rb +1 -1
- data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +1 -1
- data/lib/tapioca/static/requires_compiler.rb +6 -6
- data/lib/tapioca/static/symbol_loader.rb +14 -16
- data/lib/tapioca/static/symbol_table_parser.rb +8 -8
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +22 -29
- metadata +25 -10
@@ -111,10 +111,10 @@ module Tapioca
|
|
111
111
|
class MissingConstantError < StandardError
|
112
112
|
extend T::Sig
|
113
113
|
|
114
|
-
|
114
|
+
#: String
|
115
115
|
attr_reader :class_name
|
116
116
|
|
117
|
-
|
117
|
+
#: (String class_name) -> void
|
118
118
|
def initialize(class_name)
|
119
119
|
@class_name = class_name
|
120
120
|
super
|
@@ -123,7 +123,8 @@ module Tapioca
|
|
123
123
|
|
124
124
|
ConstantType = type_member { { fixed: T.class_of(ActiveRecord::Base) } }
|
125
125
|
|
126
|
-
|
126
|
+
# @override
|
127
|
+
#: -> void
|
127
128
|
def decorate
|
128
129
|
return if constant.reflections.empty?
|
129
130
|
|
@@ -140,7 +141,8 @@ module Tapioca
|
|
140
141
|
class << self
|
141
142
|
extend T::Sig
|
142
143
|
|
143
|
-
|
144
|
+
# @override
|
145
|
+
#: -> T::Enumerable[Module]
|
144
146
|
def gather_constants
|
145
147
|
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
146
148
|
end
|
@@ -148,7 +150,7 @@ module Tapioca
|
|
148
150
|
|
149
151
|
private
|
150
152
|
|
151
|
-
|
153
|
+
#: (RBI::Scope mod) -> void
|
152
154
|
def populate_nested_attribute_writers(mod)
|
153
155
|
constant.nested_attributes_options.keys.each do |association_name|
|
154
156
|
mod.create_method(
|
@@ -159,7 +161,7 @@ module Tapioca
|
|
159
161
|
end
|
160
162
|
end
|
161
163
|
|
162
|
-
|
164
|
+
#: (RBI::Scope mod) -> void
|
163
165
|
def populate_associations(mod)
|
164
166
|
constant.reflections.each do |association_name, reflection|
|
165
167
|
if reflection.collection?
|
@@ -178,13 +180,7 @@ module Tapioca
|
|
178
180
|
end
|
179
181
|
end
|
180
182
|
|
181
|
-
|
182
|
-
params(
|
183
|
-
klass: RBI::Scope,
|
184
|
-
association_name: T.any(String, Symbol),
|
185
|
-
reflection: ReflectionType,
|
186
|
-
).void
|
187
|
-
end
|
183
|
+
#: (RBI::Scope klass, (String | Symbol) association_name, ReflectionType reflection) -> void
|
188
184
|
def populate_single_assoc_getter_setter(klass, association_name, reflection)
|
189
185
|
association_class = type_for(reflection)
|
190
186
|
association_type = as_nilable_type(association_class)
|
@@ -247,13 +243,7 @@ module Tapioca
|
|
247
243
|
end
|
248
244
|
end
|
249
245
|
|
250
|
-
|
251
|
-
params(
|
252
|
-
klass: RBI::Scope,
|
253
|
-
association_name: T.any(String, Symbol),
|
254
|
-
reflection: ReflectionType,
|
255
|
-
).void
|
256
|
-
end
|
246
|
+
#: (RBI::Scope klass, (String | Symbol) association_name, ReflectionType reflection) -> void
|
257
247
|
def populate_collection_assoc_getter_setter(klass, association_name, reflection)
|
258
248
|
association_class = type_for(reflection)
|
259
249
|
relation_class = relation_type_for(reflection)
|
@@ -279,11 +269,7 @@ module Tapioca
|
|
279
269
|
)
|
280
270
|
end
|
281
271
|
|
282
|
-
|
283
|
-
params(
|
284
|
-
reflection: ReflectionType,
|
285
|
-
).returns(String)
|
286
|
-
end
|
272
|
+
#: (ReflectionType reflection) -> String
|
287
273
|
def type_for(reflection)
|
288
274
|
validate_reflection!(reflection)
|
289
275
|
|
@@ -292,11 +278,7 @@ module Tapioca
|
|
292
278
|
T.must(qualified_name_of(reflection.klass))
|
293
279
|
end
|
294
280
|
|
295
|
-
|
296
|
-
params(
|
297
|
-
reflection: ReflectionType,
|
298
|
-
).void
|
299
|
-
end
|
281
|
+
#: (ReflectionType reflection) -> void
|
300
282
|
def validate_reflection!(reflection)
|
301
283
|
# Check existence of source reflection, first, since, calling
|
302
284
|
# `.klass` also tries to go through the source reflection
|
@@ -320,7 +302,7 @@ module Tapioca
|
|
320
302
|
raise MissingConstantError, class_name
|
321
303
|
end
|
322
304
|
|
323
|
-
|
305
|
+
#: (ReflectionType reflection) -> String?
|
324
306
|
def declaration(reflection)
|
325
307
|
case reflection
|
326
308
|
when ActiveRecord::Reflection::HasOneReflection
|
@@ -340,7 +322,7 @@ module Tapioca
|
|
340
322
|
end
|
341
323
|
end
|
342
324
|
|
343
|
-
|
325
|
+
#: (ReflectionType reflection) -> Array[RBI::Comment]
|
344
326
|
def association_comments(reflection)
|
345
327
|
anchor_name = case reflection
|
346
328
|
when ActiveRecord::Reflection::HasOneReflection
|
@@ -374,11 +356,7 @@ module Tapioca
|
|
374
356
|
end
|
375
357
|
end
|
376
358
|
|
377
|
-
|
378
|
-
params(
|
379
|
-
reflection: ReflectionType,
|
380
|
-
).returns(String)
|
381
|
-
end
|
359
|
+
#: (ReflectionType reflection) -> String
|
382
360
|
def relation_type_for(reflection)
|
383
361
|
validate_reflection!(reflection)
|
384
362
|
|
@@ -398,11 +376,7 @@ module Tapioca
|
|
398
376
|
end
|
399
377
|
end
|
400
378
|
|
401
|
-
|
402
|
-
params(
|
403
|
-
reflection: ReflectionType,
|
404
|
-
).returns(T::Boolean)
|
405
|
-
end
|
379
|
+
#: (ReflectionType reflection) -> bool
|
406
380
|
def polymorphic_association?(reflection)
|
407
381
|
if reflection.through_reflection?
|
408
382
|
polymorphic_association?(reflection.source_reflection)
|
@@ -126,7 +126,8 @@ module Tapioca
|
|
126
126
|
|
127
127
|
ConstantType = type_member { { fixed: T.class_of(ActiveRecord::Base) } }
|
128
128
|
|
129
|
-
|
129
|
+
# @override
|
130
|
+
#: -> void
|
130
131
|
def decorate
|
131
132
|
return unless constant.table_exists?
|
132
133
|
|
@@ -165,7 +166,8 @@ module Tapioca
|
|
165
166
|
class << self
|
166
167
|
extend T::Sig
|
167
168
|
|
168
|
-
|
169
|
+
# @override
|
170
|
+
#: -> T::Enumerable[Module]
|
169
171
|
def gather_constants
|
170
172
|
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
171
173
|
end
|
@@ -175,7 +177,7 @@ module Tapioca
|
|
175
177
|
|
176
178
|
ColumnTypeOption = Helpers::ActiveRecordColumnTypeHelper::ColumnTypeOption
|
177
179
|
|
178
|
-
|
180
|
+
#: -> ColumnTypeOption
|
179
181
|
def column_type_option
|
180
182
|
@column_type_option ||= T.let(
|
181
183
|
ColumnTypeOption.from_options(options) do |value, default_column_type_option|
|
@@ -188,15 +190,7 @@ module Tapioca
|
|
188
190
|
)
|
189
191
|
end
|
190
192
|
|
191
|
-
|
192
|
-
params(
|
193
|
-
klass: RBI::Scope,
|
194
|
-
name: String,
|
195
|
-
methods_to_add: T.nilable(T::Array[String]),
|
196
|
-
return_type: String,
|
197
|
-
parameters: T::Array[RBI::TypedParam],
|
198
|
-
).void
|
199
|
-
end
|
193
|
+
#: (RBI::Scope klass, String name, Array[String]? methods_to_add, ?return_type: String, ?parameters: Array[RBI::TypedParam]) -> void
|
200
194
|
def add_method(klass, name, methods_to_add, return_type: "void", parameters: [])
|
201
195
|
klass.create_method(
|
202
196
|
name,
|
@@ -205,14 +199,7 @@ module Tapioca
|
|
205
199
|
) if methods_to_add.nil? || methods_to_add.include?(name)
|
206
200
|
end
|
207
201
|
|
208
|
-
|
209
|
-
params(
|
210
|
-
klass: RBI::Scope,
|
211
|
-
attribute_name: String,
|
212
|
-
column_name: String,
|
213
|
-
methods_to_add: T.nilable(T::Array[String]),
|
214
|
-
).void
|
215
|
-
end
|
202
|
+
#: (RBI::Scope klass, String attribute_name, ?String column_name, ?Array[String]? methods_to_add) -> void
|
216
203
|
def add_methods_for_attribute(klass, attribute_name, column_name = attribute_name, methods_to_add = nil)
|
217
204
|
getter_type, setter_type = Helpers::ActiveRecordColumnTypeHelper
|
218
205
|
.new(constant, column_type_option: column_type_option)
|
@@ -277,12 +264,20 @@ module Tapioca
|
|
277
264
|
"saved_change_to_#{attribute_name}?",
|
278
265
|
methods_to_add,
|
279
266
|
return_type: "T::Boolean",
|
267
|
+
parameters: [
|
268
|
+
create_kw_opt_param("from", type: "T.untyped", default: "T.unsafe(nil)"),
|
269
|
+
create_kw_opt_param("to", type: "T.untyped", default: "T.unsafe(nil)"),
|
270
|
+
],
|
280
271
|
)
|
281
272
|
add_method(
|
282
273
|
klass,
|
283
274
|
"will_save_change_to_#{attribute_name}?",
|
284
275
|
methods_to_add,
|
285
276
|
return_type: "T::Boolean",
|
277
|
+
parameters: [
|
278
|
+
create_kw_opt_param("from", type: "T.untyped", default: "T.unsafe(nil)"),
|
279
|
+
create_kw_opt_param("to", type: "T.untyped", default: "T.unsafe(nil)"),
|
280
|
+
],
|
286
281
|
)
|
287
282
|
|
288
283
|
# Added by ActiveModel::Dirty
|
@@ -299,8 +294,8 @@ module Tapioca
|
|
299
294
|
methods_to_add,
|
300
295
|
return_type: "T::Boolean",
|
301
296
|
parameters: [
|
302
|
-
create_kw_opt_param("from", type:
|
303
|
-
create_kw_opt_param("to", type:
|
297
|
+
create_kw_opt_param("from", type: "T.untyped", default: "T.unsafe(nil)"),
|
298
|
+
create_kw_opt_param("to", type: "T.untyped", default: "T.unsafe(nil)"),
|
304
299
|
],
|
305
300
|
)
|
306
301
|
add_method(
|
@@ -326,8 +321,8 @@ module Tapioca
|
|
326
321
|
methods_to_add,
|
327
322
|
return_type: "T::Boolean",
|
328
323
|
parameters: [
|
329
|
-
create_kw_opt_param("from", type:
|
330
|
-
create_kw_opt_param("to", type:
|
324
|
+
create_kw_opt_param("from", type: "T.untyped", default: "T.unsafe(nil)"),
|
325
|
+
create_kw_opt_param("to", type: "T.untyped", default: "T.unsafe(nil)"),
|
331
326
|
],
|
332
327
|
)
|
333
328
|
add_method(
|
@@ -69,7 +69,8 @@ module Tapioca
|
|
69
69
|
|
70
70
|
ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
|
71
71
|
|
72
|
-
|
72
|
+
# @override
|
73
|
+
#: -> void
|
73
74
|
def decorate
|
74
75
|
return if constant.__tapioca_delegated_types.nil?
|
75
76
|
|
@@ -90,7 +91,8 @@ module Tapioca
|
|
90
91
|
class << self
|
91
92
|
extend T::Sig
|
92
93
|
|
93
|
-
|
94
|
+
# @override
|
95
|
+
#: -> T::Enumerable[Module]
|
94
96
|
def gather_constants
|
95
97
|
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
96
98
|
end
|
@@ -98,7 +100,7 @@ module Tapioca
|
|
98
100
|
|
99
101
|
private
|
100
102
|
|
101
|
-
|
103
|
+
#: (RBI::Scope mod, Symbol role, Array[String] types) -> void
|
102
104
|
def populate_role_accessors(mod, role, types)
|
103
105
|
mod.create_method(
|
104
106
|
"#{role}_name",
|
@@ -119,14 +121,14 @@ module Tapioca
|
|
119
121
|
)
|
120
122
|
end
|
121
123
|
|
122
|
-
|
124
|
+
#: (RBI::Scope mod, Symbol role, Array[String] types, Hash[Symbol, untyped] options) -> void
|
123
125
|
def populate_type_helpers(mod, role, types, options)
|
124
126
|
types.each do |type|
|
125
127
|
populate_type_helper(mod, role, type, options)
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
|
131
|
+
#: (RBI::Scope mod, Symbol role, String type, Hash[Symbol, untyped] options) -> void
|
130
132
|
def populate_type_helper(mod, role, type, options)
|
131
133
|
singular = type.tableize.tr("/", "_").singularize
|
132
134
|
query = "#{singular}?"
|
@@ -54,7 +54,8 @@ module Tapioca
|
|
54
54
|
|
55
55
|
ConstantType = type_member { { fixed: T.class_of(::ActiveRecord::Base) } }
|
56
56
|
|
57
|
-
|
57
|
+
# @override
|
58
|
+
#: -> void
|
58
59
|
def decorate
|
59
60
|
return if constant.defined_enums.empty?
|
60
61
|
|
@@ -77,7 +78,8 @@ module Tapioca
|
|
77
78
|
class << self
|
78
79
|
extend T::Sig
|
79
80
|
|
80
|
-
|
81
|
+
# @override
|
82
|
+
#: -> T::Enumerable[Module]
|
81
83
|
def gather_constants
|
82
84
|
descendants_of(::ActiveRecord::Base)
|
83
85
|
end
|
@@ -85,7 +87,7 @@ module Tapioca
|
|
85
87
|
|
86
88
|
private
|
87
89
|
|
88
|
-
|
90
|
+
#: (Hash[untyped, untyped] enum_map) -> String
|
89
91
|
def type_for_enum(enum_map)
|
90
92
|
value_type = enum_map.values.map { |v| v.class.name }.uniq
|
91
93
|
value_type = if value_type.length == 1
|
@@ -97,7 +99,7 @@ module Tapioca
|
|
97
99
|
"T::Hash[T.any(String, Symbol), #{value_type}]"
|
98
100
|
end
|
99
101
|
|
100
|
-
|
102
|
+
#: (RBI::Scope klass) -> void
|
101
103
|
def generate_instance_methods(klass)
|
102
104
|
methods = constant.send(:_enum_methods_module).instance_methods
|
103
105
|
|
@@ -39,7 +39,8 @@ module Tapioca
|
|
39
39
|
ConstantType = type_member { { fixed: T.class_of(ActiveSupport::TestCase) } }
|
40
40
|
MISSING = Object.new
|
41
41
|
|
42
|
-
|
42
|
+
# @override
|
43
|
+
#: -> void
|
43
44
|
def decorate
|
44
45
|
method_names = if fixture_loader.respond_to?(:fixture_sets)
|
45
46
|
method_names_from_lazy_fixture_loader
|
@@ -60,7 +61,8 @@ module Tapioca
|
|
60
61
|
class << self
|
61
62
|
extend T::Sig
|
62
63
|
|
63
|
-
|
64
|
+
# @override
|
65
|
+
#: -> T::Enumerable[Module]
|
64
66
|
def gather_constants
|
65
67
|
return [] unless defined?(Rails.application) && Rails.application
|
66
68
|
|
@@ -70,35 +72,32 @@ module Tapioca
|
|
70
72
|
|
71
73
|
private
|
72
74
|
|
73
|
-
|
75
|
+
#: -> Class[ActiveRecord::TestFixtures]
|
74
76
|
def fixture_loader
|
75
|
-
@fixture_loader ||=
|
76
|
-
|
77
|
-
T.unsafe(self).include(ActiveRecord::TestFixtures)
|
78
|
-
|
79
|
-
if respond_to?(:fixture_paths=)
|
80
|
-
T.unsafe(self).fixture_paths = [Rails.root.join("test", "fixtures")]
|
81
|
-
else
|
82
|
-
T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
|
83
|
-
end
|
77
|
+
@fixture_loader ||= Class.new do
|
78
|
+
T.unsafe(self).include(ActiveRecord::TestFixtures)
|
84
79
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
if respond_to?(:fixture_paths=)
|
81
|
+
T.unsafe(self).fixture_paths = [Rails.root.join("test", "fixtures")]
|
82
|
+
else
|
83
|
+
T.unsafe(self).fixture_path = Rails.root.join("test", "fixtures")
|
84
|
+
end
|
85
|
+
|
86
|
+
# https://github.com/rails/rails/blob/7c70791470fc517deb7c640bead9f1b47efb5539/activerecord/lib/active_record/test_fixtures.rb#L46
|
87
|
+
singleton_class.define_method(:file_fixture_path) do
|
88
|
+
Rails.root.join("test", "fixtures", "files")
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
T.nilable(T::Class[ActiveRecord::TestFixtures]),
|
93
|
-
)
|
91
|
+
T.unsafe(self).fixtures(:all)
|
92
|
+
end #: Class[ActiveRecord::TestFixtures]?
|
94
93
|
end
|
95
94
|
|
96
|
-
|
95
|
+
#: -> Array[String]
|
97
96
|
def method_names_from_lazy_fixture_loader
|
98
97
|
T.unsafe(fixture_loader).fixture_sets.keys
|
99
98
|
end
|
100
99
|
|
101
|
-
|
100
|
+
#: -> Array[String]
|
102
101
|
def method_names_from_eager_fixture_loader
|
103
102
|
fixture_loader.ancestors # get all ancestors from class that includes AR fixtures
|
104
103
|
.drop(1) # drop the anonymous class itself from the array
|
@@ -108,7 +107,7 @@ module Tapioca
|
|
108
107
|
end
|
109
108
|
end
|
110
109
|
|
111
|
-
|
110
|
+
#: (RBI::Scope mod, String name) -> void
|
112
111
|
def create_fixture_method(mod, name)
|
113
112
|
return_type = return_type_for_fixture(name)
|
114
113
|
mod.create_method(name) do |node|
|
@@ -135,7 +134,7 @@ module Tapioca
|
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
138
|
-
|
137
|
+
#: (String fixture_name) -> String
|
139
138
|
def return_type_for_fixture(fixture_name)
|
140
139
|
fixture_class_mapping_from_fixture_files[fixture_name] ||
|
141
140
|
fixture_class_from_fixture_set(fixture_name) ||
|
@@ -143,7 +142,7 @@ module Tapioca
|
|
143
142
|
"T.untyped"
|
144
143
|
end
|
145
144
|
|
146
|
-
|
145
|
+
#: (String fixture_name) -> String?
|
147
146
|
def fixture_class_from_fixture_set(fixture_name)
|
148
147
|
# only rails 7.1+ support fixture sets so this is conditional
|
149
148
|
return unless fixture_loader.respond_to?(:fixture_sets)
|
@@ -157,54 +156,47 @@ module Tapioca
|
|
157
156
|
model_name
|
158
157
|
end
|
159
158
|
|
160
|
-
|
159
|
+
#: -> Hash[String, String]
|
161
160
|
def fixture_class_from_active_record_base_class_mapping
|
162
|
-
@fixture_class_mapping ||=
|
163
|
-
|
164
|
-
|
165
|
-
class_name = model_class.name
|
161
|
+
@fixture_class_mapping ||=
|
162
|
+
ActiveRecord::Base.descendants.each_with_object({}) do |model_class, mapping|
|
163
|
+
class_name = model_class.name
|
166
164
|
|
167
|
-
|
168
|
-
|
165
|
+
fixture_name = class_name.underscore.gsub("/", "_")
|
166
|
+
fixture_name = fixture_name.pluralize if ActiveRecord::Base.pluralize_table_names
|
169
167
|
|
170
|
-
|
168
|
+
mapping[fixture_name] = class_name
|
171
169
|
|
172
|
-
|
173
|
-
|
174
|
-
end,
|
175
|
-
T.nilable(T::Hash[String, String]),
|
176
|
-
)
|
170
|
+
mapping
|
171
|
+
end #: Hash[String, String]?
|
177
172
|
end
|
178
173
|
|
179
|
-
|
174
|
+
#: -> Hash[String, String]
|
180
175
|
def fixture_class_mapping_from_fixture_files
|
181
|
-
@fixture_file_class_mapping ||=
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
176
|
+
@fixture_file_class_mapping ||= begin
|
177
|
+
fixture_paths = if T.unsafe(fixture_loader).respond_to?(:fixture_paths)
|
178
|
+
T.unsafe(fixture_loader).fixture_paths
|
179
|
+
else
|
180
|
+
T.unsafe(fixture_loader).fixture_path
|
181
|
+
end
|
188
182
|
|
189
|
-
|
190
|
-
|
191
|
-
|
183
|
+
Array(fixture_paths).each_with_object({}) do |path, mapping|
|
184
|
+
Dir["#{path}{.yml,/{**,*}/*.yml}"].select do |file|
|
185
|
+
next unless ::File.file?(file)
|
192
186
|
|
193
|
-
|
194
|
-
|
195
|
-
|
187
|
+
ActiveRecord::FixtureSet::File.open(file) do |fh|
|
188
|
+
fixture_name = file.delete_prefix(path.to_s).delete_prefix("/").delete_suffix(".yml")
|
189
|
+
next unless fh.model_class
|
196
190
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
end
|
191
|
+
mapping[fixture_name] = fh.model_class
|
192
|
+
rescue ActiveRecord::Fixture::FormatError
|
193
|
+
# For fixtures that are not associated to any models and just contain raw data or fixtures that
|
194
|
+
# contain invalid formatting, we want to skip them and avoid crashing
|
195
|
+
mapping[fixture_name] = MISSING
|
203
196
|
end
|
204
197
|
end
|
205
|
-
end
|
206
|
-
|
207
|
-
)
|
198
|
+
end
|
199
|
+
end #: Hash[String, String]?
|
208
200
|
end
|
209
201
|
end
|
210
202
|
end
|