class SorbetRails::ModelRbiFormatter
Attributes
available_classes[R]
model_class[R]
Public Class Methods
new(model_class, available_classes)
click to toggle source
# File lib/sorbet-rails/model_rbi_formatter.rb, line 24 def initialize(model_class, available_classes) @model_class = T.let(model_class, T.class_of(ActiveRecord::Base)) @available_classes = T.let(available_classes, T::Set[String]) begin # Load all dynamic instance methods of this model by instantiating a fake model @model_class.new unless @model_class.abstract_class? rescue StandardError => err puts "#{err.class}: Note: Unable to create new instance of #{model_class_name}" end end
Public Instance Methods
generate_base_rbi(root)
click to toggle source
# File lib/sorbet-rails/model_rbi_formatter.rb, line 70 def generate_base_rbi(root) # This is the backbone of the model_rbi_formatter. # It could live in a base plugin but I consider it not replacable and better to leave here model_relation_rbi = root.create_class( self.model_relation_class_name, superclass: "ActiveRecord::Relation", ) model_relation_rbi.create_include(self.model_query_methods_returning_relation_module_name) model_relation_rbi.create_constant( "Elem", value: "type_member(fixed: #{model_class_name})", ) model_assoc_relation_rbi = root.create_class( self.model_assoc_relation_class_name, superclass: "ActiveRecord::AssociationRelation", ) model_assoc_relation_rbi.create_include(self.model_query_methods_returning_assoc_relation_module_name) model_assoc_relation_rbi.create_constant( "Elem", value: "type_member(fixed: #{model_class_name})", ) collection_proxy_rbi = root.create_class( self.model_assoc_proxy_class_name, superclass: "ActiveRecord::Associations::CollectionProxy", ) collection_proxy_rbi.create_include(self.model_query_methods_returning_assoc_relation_module_name) collection_proxy_rbi.create_constant( "Elem", value: "type_member(fixed: #{self.model_class_name})", ) model_rbi = root.create_class( self.model_class_name, superclass: T.must(@model_class.superclass).name, ) model_rbi.create_extend(self.model_query_methods_returning_relation_module_name) model_rbi.create_type_alias( self.model_relation_type_class_name, type: self.model_relation_type_alias ) end
generate_rbi()
click to toggle source
# File lib/sorbet-rails/model_rbi_formatter.rb, line 36 def generate_rbi puts "-- Generate sigs for #{model_class_name} --" # Collect the instances of each plugin into an array plugin_instances = self.class.get_plugins.map do |plugin_klass| plugin_klass.new(model_class, available_classes) end generator = Parlour::RbiGenerator.new(break_params: 3) run_plugins(plugin_instances, generator) # Generate the base after the plugins because when ConflictResolver merge the modules, # it'll put the modules at the last position merged. Putting the base stuff # last will keep the order consistent and minimize changes when new plugins are added. generate_base_rbi(generator.root) Parlour::ConflictResolver.new.resolve_conflicts(generator.root) do |msg, candidates| puts "Conflict: #{msg}. Skip following methods" candidates.each do |c| puts "- Method `#{c.name}` generated by #{c.generated_by.class.name}" end nil end rbi = <<~MESSAGE # This is an autogenerated file for dynamic methods in #{self.model_class_name} # Please rerun bundle exec rake rails_rbi:models[#{self.model_class_name}] to regenerate. MESSAGE rbi += generator.rbi return rbi end
run_plugins(plugins, generator)
click to toggle source
# File lib/sorbet-rails/model_rbi_formatter.rb, line 121 def run_plugins(plugins, generator) allow_failure = ENV["SBR_DEBUG_MODE"] == "true" plugins.each do |plugin| begin generator.current_plugin = plugin plugin.generate(generator.root) rescue Exception => e raise e unless allow_failure puts "!!! Plugin #{plugin.class.name} threw an exception: #{e}" end end end