Class: Tapioca::Dsl::Compilers::ActiveRecordColumns

Inherits:
Tapioca::Dsl::Compiler show all
Extended by:
T::Sig
Includes:
Helpers::ActiveRecordConstantsHelper
Defined in:
lib/tapioca/dsl/compilers/active_record_columns.rb

Overview

‘Tapioca::Dsl::Compilers::ActiveRecordColumns` refines RBI files for subclasses of [`ActiveRecord::Base`](api.rubyonrails.org/classes/ActiveRecord/Base.html). This compiler is only responsible for defining the attribute methods that would be created for the columns that are defined in the Active Record model.

For example, with the following model class: ~~~rb class Post < ActiveRecord::Base end ~~~

and the following database schema:

~~~rb # db/schema.rb create_table :posts do |t|

t.string :title, null: false
t.string :body
t.boolean :published
t.timestamps

end ~~~

this compiler will produce the following methods in the RBI file ‘post.rbi`:

~~~rbi # post.rbi # typed: true class Post

include GeneratedAttributeMethods

module GeneratedAttributeMethods
  sig { returns(T.nilable(::String)) }
  def body; end

  sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
  def body=; end

  sig { returns(T::Boolean) }
  def body?; end

  sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
  def created_at; end

  sig { params(value: ::ActiveSupport::TimeWithZone).returns(::ActiveSupport::TimeWithZone) }
  def created_at=; end

  sig { returns(T::Boolean) }
  def created_at?; end

  sig { returns(T.nilable(T::Boolean)) }
  def published; end

  sig { params(value: T::Boolean).returns(T::Boolean) }
  def published=; end

  sig { returns(T::Boolean) }
  def published?; end

  sig { returns(::String) }
  def title; end

  sig { params(value: ::String).returns(::String) }
  def title=(value); end

  sig { returns(T::Boolean) }
  def title?; end

  sig { returns(T.nilable(::ActiveSupport::TimeWithZone)) }
  def updated_at; end

  sig { params(value: ::ActiveSupport::TimeWithZone).returns(::ActiveSupport::TimeWithZone) }
  def updated_at=; end

  sig { returns(T::Boolean) }
  def updated_at?; end

  ## Also the methods added by https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html
  ## Also the methods added by https://api.rubyonrails.org/classes/ActiveModel/Dirty.html
  ## Also the methods added by https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html
end

end ~~~

Constant Summary collapse

ConstantType =
type_member { { fixed: T.class_of(ActiveRecord::Base) } }

Constants included from Helpers::ActiveRecordConstantsHelper

Helpers::ActiveRecordConstantsHelper::AssociationMethodsModuleName, Helpers::ActiveRecordConstantsHelper::AssociationRelationClassName, Helpers::ActiveRecordConstantsHelper::AssociationRelationMethodsModuleName, Helpers::ActiveRecordConstantsHelper::AssociationRelationWhereChainClassName, Helpers::ActiveRecordConstantsHelper::AssociationsCollectionProxyClassName, Helpers::ActiveRecordConstantsHelper::AttributeMethodsModuleName, Helpers::ActiveRecordConstantsHelper::CommonRelationMethodsModuleName, Helpers::ActiveRecordConstantsHelper::ReflectionType, Helpers::ActiveRecordConstantsHelper::RelationClassName, Helpers::ActiveRecordConstantsHelper::RelationMethodsModuleName, Helpers::ActiveRecordConstantsHelper::RelationWhereChainClassName

Constants included from Runtime::Reflection

Runtime::Reflection::ANCESTORS_METHOD, Runtime::Reflection::CLASS_METHOD, Runtime::Reflection::CONSTANTS_METHOD, Runtime::Reflection::EQUAL_METHOD, Runtime::Reflection::METHOD_METHOD, Runtime::Reflection::NAME_METHOD, Runtime::Reflection::OBJECT_ID_METHOD, Runtime::Reflection::PRIVATE_INSTANCE_METHODS_METHOD, Runtime::Reflection::PROTECTED_INSTANCE_METHODS_METHOD, Runtime::Reflection::PUBLIC_INSTANCE_METHODS_METHOD, Runtime::Reflection::REQUIRED_FROM_LABELS, Runtime::Reflection::SINGLETON_CLASS_METHOD, Runtime::Reflection::SUPERCLASS_METHOD, Runtime::Reflection::UNDEFINED_CONSTANT

Constants included from SorbetHelper

SorbetHelper::FEATURE_REQUIREMENTS, SorbetHelper::SORBET_BIN, SorbetHelper::SORBET_EXE_PATH_ENV_VAR, SorbetHelper::SORBET_GEM_SPEC, SorbetHelper::SORBET_PAYLOAD_URL

Instance Attribute Summary

Attributes inherited from Tapioca::Dsl::Compiler

#constant, #root

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tapioca::Dsl::Compiler

#add_error, #compiler_enabled?, handles?, #initialize, processable_constants

Methods included from T::Generic::TypeStoragePatch

#[], #type_member, #type_template

Methods included from Runtime::Reflection

#ancestors_of, #are_equal?, #attached_class_of, #class_of, #constant_defined?, #constantize, #constants_of, #descendants_of, #file_candidates_for, #inherited_ancestors_of, #method_of, #name_of, #name_of_type, #object_id_of, #private_instance_methods_of, #protected_instance_methods_of, #public_instance_methods_of, #qualified_name_of, #resolve_loc, #signature_of, #singleton_class_of, #superclass_of

Methods included from RBIHelper

#as_nilable_type, #create_block_param, #create_kw_opt_param, #create_kw_param, #create_kw_rest_param, #create_opt_param, #create_param, #create_rest_param, #create_typed_param, #sanitize_signature_types, serialize_type_variable, #valid_method_name?, #valid_parameter_name?

Methods included from SorbetHelper

#sorbet, #sorbet_path, #sorbet_supports?

Constructor Details

This class inherits a constructor from Tapioca::Dsl::Compiler

Class Method Details

.gather_constantsObject



142
143
144
# File 'lib/tapioca/dsl/compilers/active_record_columns.rb', line 142

def gather_constants
  descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
end

Instance Method Details

#decorateObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/tapioca/dsl/compilers/active_record_columns.rb', line 107

def decorate
  return unless constant.table_exists?

  root.create_path(constant) do |model|
    model.create_module(AttributeMethodsModuleName) do |mod|
      constant.columns_hash.each_key do |column_name|
        column_name = column_name.to_s
        add_methods_for_attribute(mod, column_name)
      end

      constant.attribute_aliases.each do |attribute_name, column_name|
        attribute_name = attribute_name.to_s
        column_name = column_name.to_s
        patterns = if constant.respond_to?(:attribute_method_patterns)
          # https://github.com/rails/rails/pull/44367
          T.unsafe(constant).attribute_method_patterns
        else
          constant.attribute_method_matchers
        end
        new_method_names = patterns.map { |m| m.method_name(attribute_name) }
        old_method_names = patterns.map { |m| m.method_name(column_name) }
        methods_to_add = new_method_names - old_method_names

        add_methods_for_attribute(mod, column_name, attribute_name, methods_to_add)
      end
    end

    model.create_include(AttributeMethodsModuleName)
  end
end